# Spring Boot
# Continuous Deployment
# Docker
# PaaS
# Render
# GitHub
17 de sep de 2023
David Gracia
5 min de lectura
.
Software Engineering & Computer Science
En este artículo voy a explicar cómo configurar el despliegue continuo en Render basado en imágenes Docker de una aplicación Spring Boot.
Herramientas y tecnologías usadas en este ejemplo:
Puedes encontrar el código de esta guía en mi repositorio de GitHub.
Empecemos por lo básico. Creamos un repositorio de GitHub donde subir el código de la aplicación.
Generamos una aplicación Spring Boot en spring initializr con la siguiente configuración. Lo descargamos y lo subimos al repositorio de GitHub.
Tenemos que containerizar nuestra aplicación para que Render pueda ejecutarla como un contenedor de Docker. Para conseguirlo, necesitamos añadir un fichero Dockerfile apropiado para nuestra aplicación Spring Boot en el directorio raíz del repositorio. El siguiente fichero Dockerfile servirá para alcanzar nuestro objetivo (si estás interesado/a en los detalles de este Dockerfile, puedes consultar la guía oficial de Spring Boot Docker que he seguido).
1FROM eclipse-temurin:17.0.6_10-jre-jammy 2 3VOLUME /tmp 4ARG JAR_FILE 5COPY ${JAR_FILE} spring-boot.jar 6ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -jar /spring-boot.jar ${0} ${@}"] 7EXPOSE 8080
Ahora que ya tenemos nuestro Dockerfile listo, vamos a publicar una imagen de Docker cada vez que ocurra un push a la rama principal de nuestro repositorio. De eso se va a encargar un workflow de GitHub Actions que situaremos en la ruta «.github/workflows/on-push-to-main.yaml».
1name: On push to main 2 3on: 4 push: 5 branches: 6 - main 7 8jobs: 9 deploy_to_production: 10 runs-on: ubuntu-latest 11 12 env: 13 REGISTRY: ghcr.io 14 IMAGE_LATEST_URL: ghcr.io/dgraciac/guide-cd-render-docker-based-spring-boot:latest 15 IMAGE_COMMIT_SHA_URL: ghcr.io/dgraciac/guide-cd-render-docker-based-spring-boot:${{ github.sha }} 16 17 permissions: 18 contents: read 19 packages: write 20 21 steps: 22 - name: Checkout 23 uses: actions/checkout@v3 24 25 - name: Set up JDK 26 uses: actions/setup-java@v3 27 with: 28 distribution: 'temurin' 29 java-version: 17 30 31 - name: Gradle build 32 run: ./gradlew build -x check 33 34 - name: Build Docker images 35 run: | 36 docker build \ 37 --build-arg JAR_FILE=build/libs/guide-cd-render-docker-based-spring-boot-0.0.1-SNAPSHOT.jar \ 38 -t ${{ env.IMAGE_LATEST_URL }} \ 39 -t ${{ env.IMAGE_COMMIT_SHA_URL }} \ 40 --platform=linux/amd64 \ 41 . 42 43 - name: Log in to the Container registry 44 uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 45 with: 46 registry: ${{ env.REGISTRY }} 47 username: ${{ github.actor }} 48 password: ${{ secrets.GITHUB_TOKEN }} 49 50 - name: Push image with "commit sha" version 51 run: docker push ${{ env.IMAGE_COMMIT_SHA_URL }} 52 53 - name: Push image with "latest" version 54 run: docker push ${{ env.IMAGE_LATEST_URL }}
Subimos este cambio a la rama principal y esto iniciará un workflow run que publicará una nueva imágen de Docker de la aplicación Spring Boot en el container registry de nuestra cuenta de GitHub con dos etiquetas: «latest» y otra con el commit SHA.
Ahora que ya tenemos una URL para nuestras imágenes de Docker, vamos a configurar un servicio web en Render y vamos a conectarlo a «ghcr.io/dgraciac/guide-cd-render-docker-based-spring-boot:latest».
Seleccionamos «Deploy an existing image from a registry».
En el campo «Image URL» ponemos la URL con la etiqueta «latest»: ghcr.io/dgraciac/guide-cd-render-docker-based-spring-boot:latest.
Si tu repositorio es privado, tu container registry también lo es y tendrás que añadir unas credenciales en tu cuenta de Render para que pueda descargarse las imágenes del container registry.
Elegimos nombre del servicio web, región geográfica e «Instance Type».
En la sección «Advanced»,
Por último, creamos el servicio web.
Al cabo de unos minutos, el servicio web estará disponible en «https://guide-cd-render-docker-based-spring-boot.onrender.com». Para comprobar que la aplicación Spring Boot es accesible públicamente, pega esta URL en tu navegador: https://guide-cd-render-docker-based-spring-boot.onrender.com/actuator/health. Si todo ha ido bien, deberías ver el siguiente mensaje: {"status":"UP","groups":["liveness","readiness"]}
Ahora ya podemos deplegar manualmente la versión «latest» de nuestra aplicación Spring Boot desde el dashboard de Render.
Pero lo que realmente nos va a facilitar la vida es que nuestro servicio web se despliegue automáticamente cada vez que se publique una nueva imágen Docker de la aplicación. Es decir, despliegue continuo.
Para configurar el despliegue continuo vamos a usar el webhook que nos ofrece Render para iniciar un nuevo despliegue.
Tenemos que añadir un paso más al final de nuestro workflow de GitHub para que llame al webhook con la URL de la imagen Docker que tiene la etiqueta commit SHA (tiene que ser URL encoded).
1- name: Trigger deploy in Render 2 run: | 3 status_code="$(curl --silent --output /dev/null --get -w "%{http_code}" --data-urlencode "imgURL=${{ env.IMAGE_COMMIT_SHA_URL }}" ${{ secrets.RENDER_DEPLOY_WEBHOOK }})" 4 echo $status_code 5 expected_status_code="200" 6 if [ $status_code != $expected_status_code ]; then 7 exit 1 8 fi
Las opciones que se pasan al comando curl sirven para codificar la URL que añadimos al query string y poder obtener el código de respuesta para hacer fallar el workflow en caso de que Render nos conteste con un error.
Solo falta mantener la URL del webhook en secreto para evitar riesgos. Así que creamos un secreto «RENDER_DEPLOY_WEBHOOK» en nuestro repositorio de GitHub (ver documentación oficial).
En mi caso, también añado esto al job del workflow porque he configurado el secreto como un secreto del entorno de producción.
1environment: 2 name: production 3 url: https://guide-cd-render-docker-based-spring-boot.onrender.com