Volviendo a la serie de «aprovechándome de lo que he montado», voy a explicaros como he montado mi Pipeline de Jenkins para Angular Dockerizado paso a paso y con el código al final.

🧐¿Por qué crear un pipeline?
¿Te preguntas el porqué? Bueno, entonces es que probablemente no hayas descubierto aún el mágico mundo de la integración continua.
Con esto lograrás que haciendo un simple push a la rama que tu decidas, se despliegue en «producción» tus nuevos desarrollos de manera automática en cuestión de minutos, te avisará si hay errores notificandote al email, podrías cancelar la subidas si tus tests fallan, etc.
🔨Creando el pipeline script
🌳Environment
Vamos a crear las variables de entorno que usaremos en los siguientes pasos de nuestro pipeline, así tendremos localizadas las mísmas.
environment {
registry = "usuario/proyecto"
registryDomain = 'https://registry.usuario.com'
registryCredentials = '111111-fg04-1234-5678-0234ab56c789'
dockerImage = ''
previousContainerId = sh(script: 'docker ps -aqf "name=miproyectocontainer"', returnStdout: true).trim()
}
☑️Stages
🏁Init
Simplemente en este paso mostraremos información del build, así tendremos un poco mas controlado el mismo.
stage('Init') {
steps {
echo "Running job: ${env.JOB_NAME}\nbuild: ${env.BUILD_ID} - ${env.BUILD_URL}\nUrl: ${env.RUN_DISPLAY_URL}"
}
}
⬇️ Download
Descargaremos el código desde nuestro repositorio .
stage('Download') {
steps {
git branch: 'main', credentialsId: '1234567-1a2b-4545-a1k3-210b333cc391', url: 'https://github.com/usuario/proyecto.git'
}
}
🚚 NPM Install
Instalaremos las dependencias de nuestro proyecto.
stage('NPM Install') {
steps {
sh 'npm install --legacy-peer-deps'
}
}
👷🏻 NGBuild
Buildeamos nuestro proyecto para producción.
stage('NG Build') {
steps {
sh 'npm run build --prod'
}
}
📦 Build Image
Crearemos la imagen docker del proyecto.
stage('Build Image') {
steps {
script {
dockerImage = docker.build registry + ":lts"
}
}
}
🚀 Deploy Image
Desplegamos nuestra imagen en Docker.
stage('Deploy Image') {
steps {
script {
docker.withRegistry(registryDomain, registryCredentials) {
dockerImage.push()
}
}
}
}
🗑️ Remove previous container
Eliminaremos, si existe, el contenedor anterior.
stage('Remove previous container') {
steps {
script {
try {
if (previousContainerId) {
sh 'docker rm -f ${previousContainerId}'
}
} catch (Exception e) {
echo 'No hay contenedor previo'
}
}
}
}
🔄 Recreate container
Recrearemos el contenedor con nuestra nueva imagen actualizada. En el siguiente snippet de código se usan las variables de entornos para desplegar con nginx y ssl automático.
stage('Recreate container') {
steps {
sh 'docker run -d --name miproyectocontainer -e VIRTUAL_HOST="proyecto.domain.com" -e VIRTUAL_PORT=80 -e LETSENCRYPT_HOST="proyecto.domain.com" -e LETSENCRYPT_EMAIL="contact@domain.com" --expose 80 -p 801:80 --restart always --net bridge registry.domain.com/usuario/proyecto:lts'
}
}
⏭️ Postbuild
Tras los stages, idealmente crearemos un postbuild para recibir un poco de feedback de lo que ha pasado. Lo dividiremos en 3 secciones, failure para cuando falla, success para cuando todo ha ido bien y always que siempre se ejecutará.
❌ Failure
Enviaremos un email con los datos del build que ha fallado.
failure {
mail bcc: '',
body: "Job - \"${env.JOB_NAME}\" build: ${env.BUILD_NUMBER}\n\nView the log at:\n ${env.BUILD_URL}",
to: 'contact@domain.com',
from: 'Jenkins Domain<jenkins@domain.com>',
subject: "[${env.JOB_NAME}] Build ${env.BUILD_NUMBER} ❌"
echo 'Email Failure Enviado'
}
✅ Success
Enviaremos un email con los datos del build que ha pasado.
success {
mail bcc: '',
body: "Job - \"${env.JOB_NAME}\" build: ${env.BUILD_NUMBER}\n\nView the log at:\n ${env.BUILD_URL}",
to: 'contact@domain.com',
from: 'Jenkins Domain<jenkins@domain.com>',
subject: "[${env.JOB_NAME}] Build ${env.BUILD_NUMBER} ✅"
echo 'Email Success Enviado'
}
🔁 Always
Borraremos todos los archivos y elementos que hayan sido temporales.
always {
echo 'Pipe finalizada'
deleteDir()
echo 'Directorio borrado'
sh "docker rmi ${dockerImage.id}"
echo "docker rmi ${dockerImage.id}"
}
⚙️Configurando el pipeline
Para que todo esto funcione, tendremos que tener configuradas varias cosas más.
⛓️ Url del repositorio
Tendremos que configurar la url del repositorio a vigilar.

🪝 Build Triggers
Activaremos el hook de Github.

🤖Activando el webhook en github
Tendremos que hacer alguna configuración en nuestro Github para activar su webhook.

🤓 Consideraciones
🔌 Plugins
Necesitarás tener varios plugins instalados en Jenkins:
- Docker Api
- Docker Commons
- Credentials Binding
- Email Extension
- Github
- NodeJS
- …
🔐 Credenciales
Deberás también configurar las credenciales de Jenkins para Github y para el registry de Docker.
📋Dockerfile
Para que Docker construya nuestra image, tendremos que poner nuestro Dockerfile en la raiz del proyecto.
FROM node:alpine as build-step
RUN mkdir -p /app
WORKDIR /app
COPY package.json /app
RUN npm install --legacy-peer-deps
COPY . /app
RUN npm run build-prod
#Segunda Etapa
FROM nginx:1.17.1-alpine
COPY --from=build-step /app/dist/ng-bolby /usr/share/nginx/html
COPY --from=build-step /app/nginx/default.conf /etc/nginx/conf.d/default.conf
🤔 Conclusión
Tener nuestro sistema así no ahorrará tiempo, seremos más rápido, tendremos la información que queramos y tendremos nuestra app segura y aislada, además de poder mejorar la portabilidad y escabilidad. Asi que dale una oportunidad a hacer tu propio Pipeline de Jenkins para Angular Dockerizado
Si tienes cualquier duda, sugerencia o comentario, ya sabes, a la cajita de abajo 👋🏻😎.
Oye psshhh te dejo el gist con el código completo por aquí. 😜
Deja una respuesta