Módulo 5: Docker en CI/CD
1. Introducción: Docker en CI/CD
Descripción
Sabes Docker. Construyes imágenes, escribes Dockerfiles eficientes, manejas multi-stage builds, y subes contenedores con docker-compose. Todo eso lo aprendiste en la guía #15. Pero hay un problema: cada vez que haces un cambio en tu código, abres la terminal, corres docker build, esperas 3-5 minutos, tageas manualmente, y pusheas al registry. Si trabajas en equipo, cada developer tiene su propio proceso de build — y a veces las imágenes difieren porque los ambientes locales son distintos.
Este módulo elimina ese proceso manual. Después de aquí, cada push al repositorio triggerea un build automático: la imagen se construye, se tagea con el SHA del commit (trazabilidad), se scannea por vulnerabilidades (seguridad), y se pushea al registry (disponibilidad) — todo sin intervención humana.
El cambio de mentalidad: Pasas de "buildeo Docker cuando me acuerdo" a "Docker se buildea automáticamente en cada push, con caching que lo hace rápido, tags que lo hacen rastreable, y security scanning que lo hace seguro."
Contexto: Vienes del Módulo 4, donde aprendiste a manejar secrets de forma segura en CI. Ahora esos secrets (como tokens de registries) se usan para autenticar el push de imágenes. Y lo que construyes aquí — imágenes en un registry — es exactamente lo que el Módulo 6 necesita para deployear automáticamente.
¿Dónde Estamos en la Guía?
Contexto
Esta guía tiene 8 módulos organizados en 3 fases:
Phase 1: CI Fundamentals (Módulos 1-3)
├── Módulo 1: Introducción a CI/CD y GitHub Actions ✅ Completado
├── Módulo 2: Testing Automatizado en CI ✅ Completado
└── Módulo 3: AI-Specific CI Checks ✅ Completado
Phase 2: CD & Deployment Pipelines (Módulos 4-6)
├── Módulo 4: Secrets y Environment Management ✅ Completado
├── Módulo 5: Docker en CI/CD ← ESTÁS AQUÍ
└── Módulo 6: Deployment Pipelines
Phase 3: Production Pipelines (Módulos 7-8)
├── Módulo 7: Monitoring, Notifications y Advanced Patterns
└── Módulo 8: Proyecto Integrador — Production AI Pipeline
Duración estimada del módulo: 60-90 minutos.
¿Hacia dónde vamos?
Este módulo es el paso 5 de 8. Automatizas la construcción y distribución de imágenes Docker. La progresión es deliberada:
- Primero entendiste CI (módulo 1) — workflows, jobs, steps, triggers
- Luego automatizaste testing (módulo 2) — pytest, matrix, caching, reports
- Agregaste checks AI-specific (módulo 3) — prompt regression, cost estimation
- Manejaste secrets de forma segura (módulo 4) — API keys, OIDC, environments
- Ahora automatizas Docker (este módulo) — build, tag, scan, push
- Después deployeas (módulo 6) — staging → approval → production
- Agregas monitoring (módulo 7) — notificaciones, scheduled workflows
- Integras todo (módulo 8) — pipeline completo commit-to-production
El problema: Docker build manual
Cómo se ve hoy tu flujo de Docker
Developer: "Subí un fix al endpoint de embeddings"
Terminal:
$ docker build -t mi-ai-app . # 3-5 minutos esperando
$ docker tag mi-ai-app:latest ghcr.io/user/mi-ai-app:v1.2.3 # tag manual
$ docker push ghcr.io/user/mi-ai-app:v1.2.3 # push manual
Otro developer:
$ docker build -t mi-ai-app . # Su build usa cached layers diferentes
$ docker tag mi-ai-app:latest ghcr.io/user/mi-ai-app:v1.2.3 # Mismo tag, imagen distinta!
$ docker push ghcr.io/user/mi-ai-app:v1.2.3 # Sobreescribe la anterior
Problemas visibles:
- 📋 Proceso manual repetitivo — Build, tag, push, cada vez que cambias algo
- 📋 Tags inconsistentes — ¿Quién decidió que es
v1.2.3? ¿Qué commit es eso? - 📋 Builds no reproducibles — Tu laptop tiene cache; el runner de CI no
- 📋 Sin verificación de seguridad — La imagen va al registry sin escaneo
- 📋 Sin garantía de calidad — La imagen se pushea aunque los tests fallaron
Cómo se ve después de este módulo
Developer: "Subí un fix al endpoint de embeddings"
GitHub Actions (automático):
1. Build con docker/build-push-action
2. Cache layers con GitHub Cache backend
3. Tag: sha-abc1234 + v1.2.3 (si es release)
4. Scan con trivy → 0 vulnerabilidades CRITICAL
5. Push a GHCR → ghcr.io/user/mi-ai-app:sha-abc1234
✅ Imagen disponible en 2 minutos. Trazable. Segura. Reproducible.
La diferencia: cero intervención manual, trazabilidad por commit, seguridad por escaneo, y consistencia por build centralizado.
Qué hace diferente Docker en CI vs Docker local
Diferencias clave
| Aspecto | Docker local | Docker en CI |
|---|---|---|
| Cache | Layers en disco local (persistente) | Runner limpio en cada run (sin cache por defecto) |
| Tags | Lo que tú decidas | Automático: SHA, semver, branch |
| Push | Manual (docker push) | Automático después del build |
| Seguridad | Tú decides si escaneas | Escaneo obligatorio en el pipeline |
| Reproducibilidad | Depende de tu entorno local | Idéntico en cada run (runner estandarizado) |
| Trigger | Cuando te acuerdas | Cada push/PR automáticamente |
| Multi-platform | Solo tu arquitectura | amd64 + arm64 si lo necesitas |
La diferencia más importante: el cache
En tu laptop, Docker cachea layers en disco. Si cambias solo el código (no las dependencias), el build tarda segundos porque las layers de pip install están cacheadas. En CI, cada workflow run empieza con un runner limpio — no hay cache. Sin configuración explícita, cada build descarga la imagen base y reinstala todas las dependencias desde cero.
Para un proyecto AI con dependencias pesadas (torch, transformers, langchain), esto significa builds de 5-10 minutos sin cache. Con cache configurado, 1-2 minutos. Configurar caching es la primera prioridad después del build básico, no un "nice to have."
Objetivo del módulo
Al completar este módulo serás capaz de:
- ✅ Configurar
docker/build-push-actionpara buildear imágenes automáticamente en CI - ✅ Implementar Docker layer caching en Actions: GitHub Cache backend y Registry cache backend
- ✅ Pushear imágenes a GHCR con
GITHUB_TOKENy a Docker Hub con secrets - ✅ Diseñar estrategias de tagging: SHA, semver, latest, branch-based
- ✅ Integrar image scanning con trivy para detectar vulnerabilidades en CI
- ✅ Configurar multi-platform builds (amd64 + arm64) cuando sea necesario
- ✅ Construir un Docker CI Pipeline completo como proyecto del módulo
Objetivo profesional
Cuando alguien de tu equipo haga push de un cambio, la imagen Docker se construye, se escanea, se tagea con el SHA del commit, y se pushea al registry — sin que nadie abra una terminal ni corra un solo comando. Si la imagen tiene vulnerabilidades críticas, el pipeline la bloquea. Eso es Docker en CI/CD profesional.
Contenido del módulo
Mapa de cápsulas
| # | Cápsula | Qué aprenderás | Tipo |
|---|---|---|---|
| 01 | Introducción (esta) | Por qué automatizar Docker, el problema manual, la visión | Intro |
| 02 | Build Docker Images en CI | docker/build-push-action, buildx, workflow YAML | Técnica |
| 03 | Docker Layer Caching en Actions | GitHub Cache vs Registry cache, configuración, impacto | Técnica |
| 04 | Container Registries | GHCR con GITHUB_TOKEN, Docker Hub con secrets, comparación | Técnica |
| 05 | Image Tagging Strategies | SHA, semver, latest, branch-based, rollbacks | Técnica |
| 06 | Image Scanning en CI | trivy, severidades, quality gates, interpretación | Técnica |
| 07 | Multi-Platform Builds | amd64 + arm64, QEMU, cuándo necesitarlo | Técnica |
| 08 | Proyecto: Docker CI Pipeline | Pipeline completo: build → tag → scan → push | Proyecto |
Flujo de aprendizaje
Primero construyes un build básico en CI (cápsula 02). Luego lo haces rápido con caching (cápsula 03). Después configuras a dónde pushear la imagen (cápsula 04). Aprendes a tagear para trazabilidad y rollbacks (cápsula 05). Integras escaneo de seguridad para detectar vulnerabilidades (cápsula 06). Opcionalmente, agregas multi-platform para diferentes arquitecturas (cápsula 07). Finalmente, integras todo en un pipeline completo (cápsula 08).
La progresión es: build → optimización → distribución → trazabilidad → seguridad → proyecto.
Duración estimada del módulo: 60-90 minutos.
Lo que viene del Módulo 4
Tu pipeline actual (después del Módulo 4) maneja secrets de forma segura:
name: CI Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
quality-gate:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: "pip"
- run: pip install -r requirements-dev.txt
- name: Lint
run: ruff check src/ tests/
- name: Type check
run: mypy src/ --ignore-missing-imports
- name: Tests
run: pytest tests/ -v --tb=short
- name: Prompt regression
run: python scripts/evaluate_prompts.py
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- name: Cost estimation
run: python scripts/estimate_costs.py
Funcional. Tests automatizados, checks AI-specific, secrets seguros. Pero falta un paso crucial: la imagen Docker. Tu código pasa todos los checks, ¿pero se buildea correctamente en Docker? ¿La imagen resultante es segura? ¿Está disponible en un registry para deployment?
Lo que este módulo agrega
# Lo que agregas DESPUÉS del quality gate
docker:
runs-on: ubuntu-latest
needs: quality-gate
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}:sha-${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
Un job nuevo: build, cache, tag, push. Automático. Trazable. Rápido.
Conexión con el proyecto de la guía
Proyecto de este módulo: Docker CI Pipeline
El mini-proyecto construye un pipeline completo:
- Build — Construye la imagen con
docker/build-push-action - Cache — GitHub Cache backend para builds rápidos
- Tag — SHA del commit + semver para releases
- Scan — trivy para detectar vulnerabilidades
- Push — A GHCR con autenticación vía GITHUB_TOKEN
Push / PR
↓
┌──────────────────────────────────────┐
│ Job: Docker CI Pipeline │
│ │
│ 1. Checkout + Setup Buildx │
│ 2. Login to GHCR │
│ 3. Build image (con cache) │
│ 4. Tag: sha-abc1234 + v1.2.3 │
│ 5. Scan con trivy │
│ 6. Push to GHCR │
│ │
│ Si scan CRITICAL → ❌ Block push │
│ Si scan clean → ✅ Push to registry │
└──────────────────────────────────────┘
Conexión con módulos posteriores
Módulo 4: Secrets management (tokens para registries)
↓
Módulo 5: Docker CI Pipeline (build + push imágenes) ← ESTÁS AQUÍ
↓
Módulo 6: Deployment Pipelines (deploya la imagen al servidor)
↓
Módulo 8: Pipeline integrador (lint → test → build → push → deploy)
La imagen que este pipeline produce es la que el Módulo 6 deploya a staging y production. Sin una imagen en un registry, no hay nada que deployear.
Prerequisitos
- ✅ Módulos 1-4 completados: Workflows, testing, AI checks, secrets management
- ✅ Docker fundamentals (guía #15): Dockerfile, docker build, multi-stage builds, docker-compose
- ✅ Cuenta de GitHub: Para GHCR (incluido gratuitamente)
- ✅ Python intermedio: Funciones, clases, REST APIs
Si no tienes estos prerequisitos
| Te falta | Recurso recomendado |
|---|---|
| Docker basics | Docker Essentials Guide (#15, NIEVA) |
| GitHub Actions | Módulos 1-2 de esta guía |
| Secrets en CI | Módulo 4 de esta guía |
Setup técnico
Estructura de archivos del módulo
tu-proyecto-ai/
├── .github/
│ └── workflows/
│ ├── ci.yml # Quality gate (Módulos 1-4)
│ └── docker.yml # Docker CI Pipeline (este módulo)
├── Dockerfile # Tu Dockerfile existente
├── .dockerignore # Excluir archivos innecesarios
├── src/
│ └── ai_app/
│ ├── __init__.py
│ ├── main.py # FastAPI app
│ └── chain.py # LangChain pipeline
├── tests/
│ └── test_chain.py
├── requirements.txt
└── requirements-dev.txt
Verificación rápida
# Verifica que Docker funciona
docker --version
# Output esperado: Docker version 24.x o superior
# Verifica que tu Dockerfile construye
docker build -t test:local .
# Output esperado: build exitoso
# Verifica que tienes un repo en GitHub
git remote -v
# Output esperado: origin https://github.com/tu-user/tu-repo.git
Si los tres comandos funcionan, estás listo para el módulo.
Qué NO cubre este módulo
- ❌ Docker basics: Cómo escribir un Dockerfile, multi-stage builds, docker-compose — eso es la guía #15
- ❌ Deployment: Cómo deployear la imagen a un servidor — eso es el Módulo 6
- ❌ Kubernetes: Orquestación de contenedores — eso es la guía #17
- ❌ Docker en desarrollo local: docker-compose para desarrollo — guía #15
- ❌ Custom registries: AWS ECR, Google Artifact Registry — mencionados pero no configurados
Analogía: La línea de producción automatizada
Imagina una fábrica de automóviles. En un taller artesanal, cada mecánico arma el auto completo a mano: instala el motor, pinta la carrocería, verifica que todo funcione, y lo estaciona en el lote. Es lento, inconsistente, y depende de quién lo haga.
En una fábrica moderna, la línea de producción automatiza todo: el chasis entra, se suelda automáticamente, se pinta con robots, pasa por control de calidad, y sale al lote — cada auto igual al anterior, trazable por número de serie, inspeccionado por sensores.
Tu Docker build manual es el taller artesanal. Docker en CI/CD es la línea de producción:
- Build automático = la soldadura robótica (siempre consistente)
- Cache de layers = piezas pre-fabricadas (no rehacer lo que no cambió)
- Tags con SHA = número de serie (sabes exactamente qué es cada unidad)
- Trivy scanning = control de calidad (detecta defectos antes de la entrega)
- Push al registry = estacionamiento del lote (disponible para el comprador)
El cambio de mentalidad
Antes de este módulo
Developer: "Terminé el feature de embeddings"
Developer: *abre terminal, corre docker build*
Developer: *espera 4 minutos*
Developer: *tagea manualmente como v1.3.0*
Developer: *corre docker push*
Developer: *avisa al equipo por Slack*
Ops: *descarga la imagen, verifica que funciona*
Ops: *deploya manualmente*
Tiempo total: 15-30 minutos
Confianza: "debería funcionar"
Trazabilidad: "creo que es la versión de hoy"
Después de este módulo
Developer: "Terminé el feature de embeddings"
Developer: *git push*
GitHub Actions (automático, 2 minutos):
✅ Tests pasan
✅ Imagen construida (cache → 45 segundos)
✅ Tag: sha-abc1234 + main + latest
✅ Scan: 0 vulnerabilidades CRITICAL
✅ Push a GHCR
✅ Summary en el workflow
Ops: *ve la imagen en Packages, sabe exactamente qué commit es*
Tiempo total: 2 minutos (automático)
Confianza: "tests pasaron, scan limpio"
Trazabilidad: "commit abc1234, 8 de marzo, 2:34 PM"
Esa es la diferencia entre Docker manual y Docker en CI/CD.
Test rápido de autoevaluación
Antes de empezar las cápsulas, verifica que tienes el contexto necesario:
- ¿Qué hace
docker build -t myapp .? (guía #15) - ¿Qué es un multi-stage build en Docker? (guía #15)
- ¿Cómo funcionan los secrets en GitHub Actions? (Módulo 4)
- ¿Qué es el
GITHUB_TOKEN? (Módulo 4) - ¿Qué es un artifact en GitHub Actions? (Módulo 2)
Si alguna pregunta te suena completamente nueva, revisa el módulo o guía correspondiente antes de continuar.
Evidencia de éxito
Al terminar este módulo, deberías poder:
- Configurar un workflow que buildea imágenes Docker automáticamente en cada push
- Implementar caching que reduce el build time de 5+ minutos a < 2 minutos
- Pushear imágenes a GHCR usando GITHUB_TOKEN (sin configurar secrets adicionales)
- Tagear imágenes con SHA del commit para trazabilidad total
- Integrar trivy para escanear vulnerabilidades antes del push
- Explicar cuándo multi-platform builds son necesarios y cuándo no
- Construir el Docker CI Pipeline completo del proyecto
Si marcas todos los checks → estás listo para el Módulo 6.
Resumen
- Docker build manual es el problema: Lento, inconsistente, sin trazabilidad, sin seguridad
- Docker en CI lo automatiza: Build, tag, scan, push — en cada push, sin intervención
- El cache es la primera prioridad: Sin cache, builds de 5-10 min; con cache, 1-2 min
- Tags = trazabilidad: SHA del commit te dice exactamente qué código corre en producción
- Security scanning = prevención: Detectar vulnerabilidades antes del push, no después del deploy
- GHCR es el default natural: Autenticación con GITHUB_TOKEN, mismo ecosistema que Actions
- La imagen que builds aquí es la que el Módulo 6 deploya a staging y production
Recursos adicionales
- docker/build-push-action — Action oficial para build y push de Docker images
- GitHub Container Registry Docs — Documentación de GHCR
- Docker Layer Caching in CI — Cómo funciona el cache de Docker
- trivy — Container Scanner — Escáner de vulnerabilidades para imágenes
- GitHub Actions — Publishing Docker Images — Guía oficial de GitHub
- Docker Essentials Guide (#15, NIEVA) — Prerequisito: fundamentos de Docker