Skip to content

CI/CD con Ejemplos

La sigla CI se refiere a la Integración Continua, mientras la sigla CD significa Despliegue Continuo, facetas que hacen parte de la automatización en DevOps. En este texto quiero presentar con algun ejemplo la combinación ciertas herramientas que hace posible un ejercicio práctico en este asunto.

Para ello usaremos lo siguiente: Docker para uso de contenedores, GitHub como Repo, Terraform como IaC (infraestructura como código), Azure Pipelines y AWS (infraestructura operable en la nube).

Se asume que tienes alguna nociones en las tecnologías mecionadas (GitHub, Docker, AWS, etc.), siendo requisito para realizar una práctica.


Nuestro ejercicio de ejemplo en Node.js

Nuestro programa de ejemplo correspondería a código Node.js y tendría un código como el siguiente:

js
const service = require('restana')();
const os = require('os');
const port = 3000;

service.get('/', (req, res) => {
    const apiVersion = '1.0.0';
    const nodeVersion = process.version;
    const platform = os.type();
    const osVersion = os.version();
    const memory = os.totalmem();
    const serverTime = new Date().toLocaleString();

    const data = {
        apiVersion,
        nodeVersion,
        platform,
        osVersion,
        memory,
        serverTime
    };

    res.send(data);
});

service.start(port);

El código anterior corresponderá a nuestro archivo index.js, pero primero debemos iniciar el proyecto en una carpeta y instalar sus módulos. Para ello, podríamos ejecutar lo siguiente desde la línea de comandos:

bash
mkdir democicd
cd democicd
npm init -y
npm i restana -S
touch index.js

Ahora incorporamos el código de nuestro programa y podemos verificar su funcionamiento ejecutando: node index.js (consultamos en un navegador la dirección: localhost:3000).

Puedes revisar ejemplo final en mi repo: https://github.com/kaesar/cicddemo

Usando Docker

Para usar contenedores con Docker, agregaremos el archivo Dockerfile con el siguiente contenido:

Dockerfile
# 1. Base Image 
FROM node:lts-alpine

# 2. Folder in container
WORKDIR /app

# 3. Files required
COPY package*.json ./

# 4. Install dependencies
RUN npm install

# Copy source code
COPY . .

# Expose API
EXPOSE 3000

# Launch service
CMD ["node", "index.js"]

Guardamos nuestro archivo Dockerfile y usamos los comandos para construir y lanzar nuestro contenedor así:

bash
docker pull node:lts-alpine
docker build -t democicd .
docker run -p 3000:3000 democicd &

El primer comando solo sirve para garantizar la descarga correcta de la imagen y evitar error de credenciales, de lo contario podría omitirse.

En el caso de usar Docker con Colima (un mecanismo de virtualización para macOS/Linux) tendría que iniciarse primero con el comando: colima start

Comandos fundamentales para el ejercicio

Para continuar con el ejercicio, con base en los videos de arriba, dejo los comandos fundamentales que soportan un enfoque programatico, y que su vez se podrían soportar un pipeline.

App & Contenedor

bash
# Checkout (clone the repo)
git clone https://github.com/kaesar/cicddemo.git
# Setup modules
npm install
# Build distribution
npm run build
# Build image for container
docker build -t cicddemo:v1 .
# Launch container locally
docker run -d -p 3000:3000 --name cicddemo cicddemo:v1
# Check container logs (for status)
docker logs cicddemo
# Stop contaiiner
docker stop cicddemo

Podría usarse también bun en lugar de node

Aprovisionamiento preliminar de acceso AWS

bash
# Create IAM user
aws iam create-user --user-name cicd-user
# Create access Key
aws iam create-access-key --user-name cicd-user
# Attach required policies
aws iam attach-user-policy --user-name cicd-user --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess
aws iam attach-user-policy --user-name cicd-user --policy-arn arn:aws:iam::aws:policy/AWSAppRunnerFullAccess
aws iam attach-user-policy --user-name cicd-user --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser
aws iam attach-user-policy --user-name cicd-user --policy-arn arn:aws:iam::aws:policy/AdministratorAccess
# Check user
aws iam list-users
aws iam list-groups-for-user --user cicd-user

Estas sentencias habilitan el usuario que se usaría como ejecutar de un pipeline o de depliegue de infraestructura

Aprovisionamiento de Recipientes para Imagen y Bucket en AWS

bash
# Create repository for images in ECR
aws ecr create-repository --repository-name cicd-hub --region us-east-1
# Login to connect with ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com
# Tagged the image
docker tag cicddemo:v1 123456789012.dkr.ecr.us-east-1.amazonaws.com/cicd-hub:v1
# Upload the image with tag
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/cicd-hub:v1
# Bucket for terraform state
aws s3api create-bucket --bucket tfstate-demo-2023 -region us-east-1

El primer comando se ejecuta una sola vez para establecer repositorio de imagen.
El último comando se refiere al archivo de estado de Terraform

Despliegue con IaC (Infraestructure as Code)

bash
# Terraform steps: init - validate - plan - apply
cd iac
terraform init
terraform validate
terraform plan -out=tfplan
terraform apply "tfplan" -auto-approve

Puedes remover los recursos ejecutando: terraform destroy
Recuerda reemplazar la cuenta 123456789012 por la que corresponda