Pipeline de Jenkins para Angular Dockerizado

Tiempo de lectura: 4 minutos

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.

Configurando Github project url en Jenkins.
Configurando Github project url en Jenkins.
🪝 Build Triggers

Activaremos el hook de Github.

Activando Github hook trigger en Jenkins.
Activando Github hook trigger en Jenkins.
🤖Activando el webhook en github

Tendremos que hacer alguna configuración en nuestro Github para activar su webhook.

Configurando webhook del repositorio de Github.
Configurando webhook del repositorio de Github.

🤓 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í. 😜

Comentarios

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio está protegido por reCAPTCHA y se aplican la política de privacidad y los términos de servicio de Google.