DEV Community

Luis_Zapata_Yamo
Luis_Zapata_Yamo

Posted on • Edited on

Implementación de una Aplicación SpringBoot Utilizando Docker y Jenkins (Docker-outside-of-Docker - DooD)

Inicialmente tenemos que instalar docker en nuestra maquina host, en este caso estoy en windows, Docker Desktop.

Importante entrar a docker desktop y habilitar en settings

epose daemon

Para fines prácticos se ha realizado pasos que se podrían mejorar usando nodos en Jenkins.

Usaremos el concepto de construcción de contenedores a partir de DockerFiles y usando Docker compose.

Lo que haremos es un flujo para que cuando realicemos un push a nuestro repositorio remoto Jenkins pueda iniciar un pipeline que permita la creación de un contenedor de una aplicación.

Creación de contenedor Jenkins y Base de datos

DockerFile.jenkinslocal

Este primer DockerFile es para el contenedor Jenkins, llamado DockerFile.jenkinslocal.

# Utiliza la imagen oficial de Jenkins FROM jenkins/jenkins:lts # Cambia al usuario root para instalar paquetes USER root # Instala wget, dpkg y dependencias necesarias RUN apt-get update && apt-get install -y wget dpkg apt-transport-https ca-certificates curl gnupg2 software-properties-common # Instala Java RUN apt-get install -y java-common # Descarga e instala Amazon Corretto 17 ADD https://corretto.aws/downloads/latest/amazon-corretto-17-x64-linux-jdk.deb /tmp/ RUN dpkg -i /tmp/amazon-corretto-17-x64-linux-jdk.deb # Limpia el cache de apt y elimina el paquete de instalación de Corretto RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/amazon-corretto-17-x64-linux-jdk.deb # Descarga e instala Maven ADD https://dlcdn.apache.org/maven/maven-3/3.9.6/binaries/apache-maven-3.9.6-bin.tar.gz /opt/ RUN tar -xzf /opt/apache-maven-3.9.6-bin.tar.gz -C /opt/ ENV PATH="/opt/apache-maven-3.9.6/bin:${PATH}" # Instala Docker CLI RUN curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - RUN add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" RUN apt-get update && apt-get install -y docker-ce-cli # Agrega el usuario de Jenkins al grupo docker RUN groupadd docker RUN usermod -aG docker jenkins # Cambia al usuario de Jenkins USER jenkins 
Enter fullscreen mode Exit fullscreen mode

Se necesita tener instalado en el contenedor de jenkins:

  • Dependencias necesarias
  • Java, en este caso usando Amazon Coretto 17
  • Maven
  • El daemon de docker

Creación del docker-compose.yml

Este docker file sera usado dentro del docker-compose.yml y dentro también crearemos el contenedor de la base de datos con parámetros establecidos para crear una bd inicial llamada crud.

version: '3.8' services:   jenkinslocal:     container_name: jenkinslocal     build:       context: .       dockerfile: Dockerfile.jenkinslocal     ports:       - "8080:8080"       - "500:5000"     environment:       JAVA_OPTS: "-Djenkins.install.runSetupWizard=false"       DOCKER_HOST: "tcp://host.docker.internal:2375"     depends_on:       - postgres     volumes:       - jenkins_home:/var/jenkins_home       - /var/run/docker.sock:/var/run/docker.sock   postgres:     container_name: db-crud     image: postgres     restart: always     ports:       - "5432:5432"     environment:       POSTGRES_DB: crud       POSTGRES_USER: postgres       POSTGRES_PASSWORD: postgres volumes:   jenkins_home: 
Enter fullscreen mode Exit fullscreen mode

El primer servicio es para el contenedor de jenkins:

  • Se crea a partir del DockerFile.jenkinslocal
  • se habilitan los puertos
  • Se agrega el host del docker
  • Y como volumen se incluye la ruta del socket de docker

El segundo servicio es para el contenedor de docker es para la base de datos, en postgres.

  • Se crea a partir de la imagen de postgres
  • Se habilitan los puertos
  • Se crean variables de entorno para configuraciones iniciales de la base de datos

Levantar Contenedores

Para poder levantar el docker compose se usa:

  • docker compose up -d

Si hacemos cambios en el internos en los servicios tenemos que hacer:

  • docker compose down
  • docker compose up -d (--detach/segundo plano)

Compose up

Configurar Aplicación

La aplicación, en este caso una api usa el puerto 8081, adicional tendro del pom.xml se define el nombre del artefacto que se crea, llamado mi-app.jar .

Es importante saber que jenkins dentro de un contenedor necesita la ip del host local

Para SpringBoot el cambio de puerto se puede hacer en el archivo application.properties :

#Ejemplo spring.application.name=crud spring.datasource.url=jdbc:postgresql://ip_local:5432/crud spring.datasource.username=postgres spring.datasource.password=postgres spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect spring.jpa.hibernate.ddl-auto=update server.port=8081 
Enter fullscreen mode Exit fullscreen mode

Para el pom en este caso se uso el finalName:

<build>         <plugins>             <plugin>                 <groupId>org.springframework.boot</groupId>                 <artifactId>spring-boot-maven-plugin</artifactId>                 <configuration>                     <excludes>                         <exclude>                             <groupId>org.projectlombok</groupId>                             <artifactId>lombok</artifactId>                         </exclude>                     </excludes>                     <finalName>mi-app</finalName>                 </configuration>             </plugin>         </plugins>     </build> 
Enter fullscreen mode Exit fullscreen mode

Creación del DockerFile para la aplicación

Requisitos para la app:

  • Instalar y configurar Java
  • Jar que se genera en el pipeline
# Dockerfile para el contenedor app-crud FROM debian:bullseye-slim # Instala wget y dpkg RUN apt-get update && apt-get install -y wget && apt-get install -y dpkg RUN apt-get update && apt-get install -y java-common # Descarga e instala Amazon Corretto 17 ADD https://corretto.aws/downloads/latest/amazon-corretto-17-x64-linux-jdk.deb /tmp/ RUN dpkg -i /tmp/amazon-corretto-17-x64-linux-jdk.deb # Limpia el cache de apt y elimina el paquete de instalación de Corretto RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/amazon-corretto-17-x64-linux-jdk.deb # Configura las variables de entorno JAVA_HOME y PATH ENV JAVA_HOME /usr/lib/jvm/java-17-amazon-corretto ENV PATH $JAVA_HOME/bin:$PATH # Define el directorio de trabajo WORKDIR /app # # Copia el JAR generado a la imagen COPY target/mi-app.jar /app/mi-app.jar # # Comando para ejecutar la aplicación CMD ["java", "-jar", "/app/mi-app.jar"] 
Enter fullscreen mode Exit fullscreen mode

Crear el JenkinsFile

Se necesita el flujo para poder hacer el despliegue.

pipeline {     agent any     environment {         DOCKER_HOST = 'tcp://host.docker.internal:2375'         CONTAINER_NAME = 'mi-app-container'         IMAGE_NAME = 'mi-app:latest'     }     stages {         stage('Build') {             steps {                 sh 'mvn clean package'             }         }         stage('Build Docker Image') {             steps {                 script {                     sh 'docker build -t ${IMAGE_NAME} -f Dockerfile.app-crud .'                 }             }         }         stage('Deploy Docker Container') {             steps {                 script {                     // Stop and remove the old container if it exists                     sh '''                     if [ "$(docker ps -aq -f name=${CONTAINER_NAME})" ]; then                         if [ "$(docker ps -aq -f status=running -f name=${CONTAINER_NAME})" ]; then                             docker stop ${CONTAINER_NAME}                         fi                         docker rm ${CONTAINER_NAME}                     fi                     '''                                         // Run the new container                     sh '''                     docker run -d --name ${CONTAINER_NAME} -p 8081:8081 ${IMAGE_NAME}                     '''                 }             }         }     } } 
Enter fullscreen mode Exit fullscreen mode

Este pipeline:

  1. Compila la aplicación y crea el JAR (mi-app.jar).
  2. Construye una imagen Docker.
  3. Despliega el contenedor, deteniendo y eliminando el existente si es necesario.

Configuración de Jenkins

Cuando se crea un contenedor jenkins hay casos que te piden una clave, esta sale en el log de ejecución del contenedor. Y luego sigues los pasos hasta ver la pagina principal

Jenkins Config

Plugins

Instala los siguientes plugins en Jenkins:

Configuración del Job

Crea un nuevo Job en Jenkins con estas configuraciones:

  • Trigger: GitHub hook trigger for GITScm polling
  • Pipeline: Pipeline script from SCM
  • SCM: Git con URL SSH
  • En Repository URL le colocamos la URL pero con el protocolo SSH
  • En credential lo dejamos vacío por ahora.

Pipeline

Abriremos una terminal del contenedor de Jenkins para crear una llave ssh:

  • docker exec -it -u jenkins id_contenedor bash

Luego dentro de la terminal

# Comandos de ejemplo cd ~ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/var/jenkins_home/.ssh/id_rsa): # Output... eval $(ssh-agent -s) ssh-add .ssh/id_rsa # Reconoceremos a github para la conexion por ssh ssh -T git@github.com # Mostramos la llave privada cat .ssh/id_rsa # Mostramos la llave publica cat .ssh/id_rsa.pub 
Enter fullscreen mode Exit fullscreen mode

Para agregar la llave privada a las credenciales de Jenkins hacemos los iguiente:

  • Abrimos la interfaz de jenkins y vamos a la configuración del job creado y agregamos una

Add credential

Les saldrá una ventana asi

Credential

  • En Kind le colocamos SSH Username with private key
  • El ID debe ser único a la otras credenciales que ya tienes
  • En Private Key le das click en Enter directly para agregar la llave privada directamente y le damos en Add.
  • Luego si es que la llave tiene clave la agregamos en el campo Passphrase
  • Al final de dan en agregar para guardar la credencial.

La llave publica la agregaremos al repositorio remoto en Settings>Deploys Keys>Add deploy key.

Add deploy key

Vamos al Job creado y la credencial ya podríamos escogerla sin inconvenientes.

Cuando se ejecute el pipeline se creara un contenedor y ya estaria el deploy

Contenedor pipeline

Top comments (0)