Repasemos las herramientas para construir pipelines CI/CD:
- Jenkins: el abuelo de las herramientas CI/CD, potente y configurable.
- GitHub Actions: integrado en GitHub, cómodo y rápido.
- GitLab CI/CD: una gran herramienta para pipelines si usas GitLab.
- CircleCI: solución en la nube, fácil de configurar.
- Bitbucket Pipelines: herramienta para CI/CD en el ecosistema de Atlassian.
Para esta lección vamos a usar GitLab CI/CD — es sencillo, visual y se integra muy bien con Docker.
Preparación
Paso 1: Crea un repositorio en GitLab
Para empezar, asegúrate de tener un repositorio que contenga tu aplicación Spring Boot. Si no, crea uno nuevo y sube todo el proyecto.
Paso 2: Configurar el archivo .gitlab-ci.yml
GitLab CI/CD usa el archivo .gitlab-ci.yml para definir cómo ejecutar el pipeline. Este archivo debe estar en la raíz del repositorio.
Crear el pipeline CI/CD
Paso 1: Configuración mínima .gitlab-ci.yml
Empezamos con un ejemplo sencillo que ejecuta tests de Java y construye la aplicación Spring Boot:
stages: # Definimos las etapas del pipeline
- test
- build
test-job: # Tarea para la etapa test
stage: test
image: maven:3.8.6-jdk-11 # Usamos la imagen con Maven y JDK
script:
- mvn test # Ejecutar tests
build-job: # Tarea para la etapa build
stage: build
image: maven:3.8.6-jdk-11
script:
- mvn package -DskipTests # Construir el jar
artifacts:
paths:
- target/*.jar # Guardamos el jar como artifact
stages: definen la secuencia de ejecución del pipeline. Primerotest, luegobuild.image: indica la imagen Docker que se usará para ejecutar la tarea. En nuestro caso es Maven + JDK.script: comandos que se ejecutan dentro de la tarea.
Paso 2: Añadimos Docker al pipeline
Ahora añadimos una etapa que construye la imagen Docker y la sube a Docker Hub.
stages:
- test
- build
- dockerize
dockerize-job:
stage: dockerize
image: docker:latest # Usamos la imagen Docker
services:
- docker:dind # Docker-in-Docker para gestionar contenedores
before_script: # Autenticación en Docker Hub
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
script:
- docker build -t $DOCKER_USERNAME/my-spring-app:$CI_COMMIT_SHORT_SHA . # Construir la imagen
- docker push $DOCKER_USERNAME/my-spring-app:$CI_COMMIT_SHORT_SHA # Publicar la imagen
Ten en cuenta:
servicesincluyedocker:dind, para que el GitLab Runner pueda ejecutar comandos Docker.before_scriptse usa para acciones previas, como hacer login en Docker Hub.$CI_COMMIT_SHORT_SHA— variable que contiene los primeros 8 caracteres del hash del commit. Así puedes identificar la imagen de forma única.
Paso 3: Añadimos el despliegue en la nube
Supongamos que desplegamos la app en un servidor vía SSH. Para eso añadimos la etapa deploy:
stages:
- test
- build
- dockerize
- deploy
deploy-job:
stage: deploy
image: ubuntu:latest
before_script:
- apt-get update && apt-get install -y ssh # Instalamos el cliente SSH
script:
- ssh $DEPLOY_USER@$DEPLOY_HOST "docker pull $DOCKER_USERNAME/my-spring-app:$CI_COMMIT_SHORT_SHA && docker stop my-spring-app || true && docker rm my-spring-app || true && docker run -d --name my-spring-app -p 8080:8080 $DOCKER_USERNAME/my-spring-app:$CI_COMMIT_SHORT_SHA"
Qué ocurre aquí:
- Nos conectamos al servidor vía SSH.
- Hacemos docker pull de la imagen más reciente de nuestra app.
- Paramos y eliminamos el contenedor viejo (si estaba corriendo).
- Arrancamos un contenedor nuevo.
Variables de entorno
Para que el pipeline funcione necesitamos definir variables de entorno en GitLab:
$DOCKER_USERNAME— nombre de usuario de Docker Hub.$DOCKER_PASSWORD— contraseña de Docker Hub.$DEPLOY_USER— usuario SSH para el despliegue.$DEPLOY_HOST— host al que se despliega la aplicación.
Puedes configurarlas en Settings → CI/CD → Variables del proyecto en GitLab.
Archivo completo .gitlab-ci.yml
Al final obtenemos este archivo:
stages:
- test
- build
- dockerize
- deploy
test-job:
stage: test
image: maven:3.8.6-jdk-11
script:
- mvn test
build-job:
stage: build
image: maven:3.8.6-jdk-11
script:
- mvn package -DskipTests
artifacts:
paths:
- target/*.jar
dockerize-job:
stage: dockerize
image: docker:latest
services:
- docker:dind
before_script:
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
script:
- docker build -t $DOCKER_USERNAME/my-spring-app:$CI_COMMIT_SHORT_SHA .
- docker push $DOCKER_USERNAME/my-spring-app:$CI_COMMIT_SHORT_SHA
deploy-job:
stage: deploy
image: ubuntu:latest
before_script:
- apt-get update && apt-get install -y ssh # Instalamos el cliente SSH
script:
- ssh $DEPLOY_USER@$DEPLOY_HOST "docker pull $DOCKER_USERNAME/my-spring-app:$CI_COMMIT_SHORT_SHA && docker stop my-spring-app || true && docker rm my-spring-app || true && docker run -d --name my-spring-app -p 8080:8080 $DOCKER_USERNAME/my-spring-app:$CI_COMMIT_SHORT_SHA"
Depuración y errores típicos
- Problemas con Docker-in-Docker Si ves errores como
cannot connect to the Docker daemon, asegúrate de que el serviciodocker:dindesté corriendo y correctamente configurado. - SSH no funciona Comprueba que la clave SSH esté añadida en tu servidor y que las variables
$DEPLOY_USERy$DEPLOY_HOSTestén bien configuradas. - Problemas con Docker Hub Si Docker Hub devuelve error de autenticación, revisa que
$DOCKER_USERNAMEy$DOCKER_PASSWORDestén correctamente configurados.
¡Todo listo! Acabas de crear un pipeline CI/CD listo para producción para tu aplicación Spring Boot. A partir de ahora cada nueva feature se comprobará, construirá y desplegará automáticamente mientras te tomas un café.
GO TO FULL VERSION