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
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
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:
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)
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
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>
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"]
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}
'''
}
}
}
}
}
Este pipeline:
- Compila la aplicación y crea el JAR (
mi-app.jar
). - Construye una imagen Docker.
- 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
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.
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
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
Les saldrá una ventana asi
- 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.
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
Top comments (0)