Los despliegues manuales no escalan. Cada paso manual es una fuente potencial de errores y, cuanto más rápido entrega tu equipo, más se acumulan esos errores. Un pipeline de CI/CD construido sobre Docker y AWS elimina el trabajo manual del camino crítico: el código se compila, se prueba, se empaqueta como contenedor y se despliega a producción sin intervención humana en cada etapa.
Este post recorre un pipeline completo usando AWS CodePipeline, AWS CodeBuild, Amazon ECR y Amazon ECS.
¿Por qué Docker y AWS para CI/CD?
Los contenedores Docker ofrecen un comportamiento consistente entre entornos. Lo que corre localmente corre de la misma manera en CI y en producción. Los servicios de AWS gestionan el escalado y la seguridad a nivel de infraestructura, y CodePipeline une las etapas en un único flujo de trabajo automatizado.
Requisitos previos
- Una cuenta de AWS con privilegios administrativos.
- Conocimiento básico de Docker y conceptos de contenedorización.
- Familiaridad con ECS y ECR.
- Una aplicación de ejemplo (esta guía usa Node.js).
Arquitectura del Pipeline
El pipeline tiene tres etapas:
- Source: El código se envía a un sistema de control de versiones (AWS CodeCommit o GitHub).
- Build: CodeBuild construye la imagen Docker y ejecuta las pruebas.
- Deploy: La imagen se sube a ECR y ECS la despliega en un clúster.
Paso 1: Configuración del Repositorio de Origen
Para una integración fluida con AWS, AWS CodeCommit es la opción más directa.
-
Navega a la consola de AWS CodeCommit.
-
Crea un nuevo repositorio llamado
my-app-repo. -
Clona el repositorio en tu máquina local:
git clone https://git-codecommit.us-east-1.amazonaws.com/v1/repos/my-app-repo -
Agrega el código de tu aplicación y haz push:
git add . git commit -m "Initial commit" git push origin master
Paso 2: Contenedorizando la Aplicación
Crea un Dockerfile para definir cómo se empaqueta tu aplicación.
Dockerfile de ejemplo para Node.js
# Use Node.js LTS version as the base image
FROM node:18-alpine
# Set the working directory in the container
WORKDIR /usr/src/app
# Copy package.json and package-lock.json
COPY package*.json ./
# Install dependencies
RUN npm install --production
# Copy the rest of the application code
COPY . .
# Expose the application port
EXPOSE 3000
# Start the application
CMD ["node", "app.js"]
Algunos puntos a tener en cuenta: usa una imagen base mínima para mantener la imagen pequeña, copia solo los archivos necesarios para optimizar el caché de build y ejecuta los contenedores como usuario no root por seguridad.
Paso 3: Especificación de Build para CodeBuild
AWS CodeBuild necesita un archivo buildspec.yml en la raíz de tu repositorio.
buildspec.yml de ejemplo
version: 0.2
phases:
pre_build:
commands:
- echo Logging into Amazon ECR...
- $(aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin <AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com)
- REPOSITORY_URI=<AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/my-app-repo
build:
commands:
- echo Building the Docker image...
- docker build -t $REPOSITORY_URI:latest .
post_build:
commands:
- echo Pushing the Docker image...
- docker push $REPOSITORY_URI:latest
artifacts:
files:
- '**/*'
Reemplaza <AWS_ACCOUNT_ID> con tu ID real de cuenta de AWS.
Paso 4: Configuración de Amazon ECR
Amazon ECR almacena tus imágenes Docker.
- Navega a la consola de Amazon ECR.
- Crea un nuevo repositorio llamado
my-app-repo. - Anota el URI del repositorio para usarlo en
buildspec.yml.
Paso 5: Configuración de AWS CodeBuild
- Navega a la consola de AWS CodeBuild.
- Crea un nuevo proyecto de build llamado
my-app-build. - Configura:
- Source Provider: AWS CodeCommit.
- Repository:
my-app-repo. - Environment: runtime Ubuntu Standard, Docker habilitado, modo Privileged activado (requerido para builds Docker).
- Buildspec: Usa el buildspec.yml del código fuente.
Paso 6: Configuración de AWS CodePipeline
- Navega a la consola de AWS CodePipeline.
- Crea un nuevo pipeline llamado
my-app-pipeline. - Etapa Source: AWS CodeCommit,
my-app-repo, ramamaster. - Etapa Build: AWS CodeBuild, proyecto
my-app-build. - Etapa Deploy: AWS ECS,
my-ecs-cluster,my-app-service.
Paso 7: Configuración de Amazon ECS
Crear un Clúster ECS
- Navega a la consola de Amazon ECS.
- Crea un clúster llamado
my-ecs-cluster. Usa Fargate si deseas evitar la gestión de instancias EC2.
Definir una Task Definition
- Ve a Task Definitions.
- Crea
my-app-taskcon:- Task Role: IAM role con los permisos necesarios.
- Network Mode:
awsvpcpara Fargate. - Container: nombre
my-app-container, imagen desde ECR, puerto 3000 mapeado al host 80.
Crear un Service
- Ve a Services y crea
my-app-service. - Launch type: Fargate. Task definition:
my-app-task. Habilita rolling updates.
Paso 8: Probando el Pipeline
-
Realiza un cambio en el código localmente.
-
Haz push a master:
git add . git commit -m "Updated application" git push origin master -
Observa el progreso del pipeline en la consola de CodePipeline.
-
Verifica el nuevo despliegue en la consola de ECS.
Mejorando el Pipeline
Pruebas Automatizadas
Agrega comandos de prueba al buildspec.yml antes del paso de build de Docker:
phases:
build:
commands:
- echo Running unit tests...
- npm test
- echo Building Docker image...
- docker build -t $REPOSITORY_URI:latest .
Infraestructura como Código
Define todos los recursos de AWS en plantillas de CloudFormation o Terraform. Mantener el código de infraestructura en control de versiones junto al código de la aplicación hace que la configuración del entorno sea reproducible y los cambios sean auditables.
Gestión de Dependencias con CodeArtifact
AWS CodeArtifact almacena y sirve paquetes npm de forma privada. Esto es útil para compartir librerías internas entre servicios sin publicarlas en el registro público de npm.
Buenas Prácticas de Seguridad
- Asigna IAM roles con privilegios mínimos a cada componente de CodeBuild y ECS.
- Almacena los secretos en AWS Secrets Manager, no en variables de entorno ni en el código fuente.
- Configura VPCs, subnets y security groups para restringir el acceso a la red.
- Habilita CloudTrail y CloudWatch para auditoría y logging.
Monitoreo y Logging
- CloudWatch Logs recopila la salida de las tasks de ECS.
- AWS X-Ray rastrea las solicitudes a través de la aplicación desplegada.
- Configura Amazon SNS para enviar notificaciones cuando fallen las etapas del pipeline.
Optimización de Costos
- Usa capacidad Spot de ECS para workloads que toleren interrupciones.
- Ajusta correctamente la CPU y memoria de las tasks basándote en las métricas reales de CloudWatch en lugar de estimaciones.
- Revisa y elimina regularmente las imágenes ECR no utilizadas y las task definitions de ECS.
Conclusión
Una vez que este pipeline está en marcha, desplegar un cambio requiere solo un git push. CodePipeline se encarga del resto: construye la imagen, ejecuta las pruebas, hace push a ECR y despliega la nueva versión en ECS. El costo inicial de configuración es real, pero se amortiza rápidamente en tiempo ahorrado e incidentes de producción evitados.