Ir al contenido

Desarrollo Local con Docker

Un ambiente de desarrollo local bien configurado permite a los equipos trabajar de forma autónoma, rápida y consistente sin depender de ambientes compartidos. En HERA, utilizamos Docker y Docker Compose para emular localmente la infraestructura cloud (base de datos, caché, mensajería) y ejecutar los servicios de aplicación con hot-reload, replicando el comportamiento de los ambientes DEV/QA/PRD en la máquina del desarrollador.


HERA estandariza Podman como motor de contenedores corporativo para el desarrollo local. En Linux, Docker Engine es una alternativa válida al ser open source. Docker Desktop no está autorizado en Grupo Herdez por restricciones de licenciamiento corporativo — usa Podman Desktop o Docker Engine (Linux) en su lugar.

MotorLicenciaDaemonRootlessCompatibilidad
PodmanApache 2.0 (open source)Sin daemon (más seguro)Por defectoCompatible con Docker CLI y Compose
Docker Engine (Linux, alternativa)Apache 2.0 (open source)Requiere daemon rootOpcionalNativo
HerramientaPropósitoWindowsmacOSLinux
Podman DesktopMotor de contenedores + Composepodman-desktop.iopodman-desktop.ioapt/dnf install podman
Docker Engine + Compose (alternativa en Linux)Motor de contenedores (nativo)apt/yum install docker-ce docker-compose-plugin
Docker ScoutEscaneo de vulnerabilidades en imágenesIncluido en Docker Desktop / CLI pluginIncluido en Docker Desktop / CLI plugindocker scout CLI plugin
VS CodeEditor con extensión Docker/Podmancode.visualstudio.comIgualIgual
GitControl de versionesgit-scm.combrew install gitapt install git
ExtensiónPropósito
Docker (ms-azuretools.vscode-docker)Gestión visual de contenedores, imágenes y compose
Dev Containers (ms-vscode-remote.remote-containers)Desarrollo dentro de un contenedor con todas las herramientas
Docker Compose (p1c2u.docker-compose)Autocompletado y validación de docker-compose.yml
GitLab Workflow (GitLab.gitlab-workflow)Integración con pipelines de GitLab HERA

El ambiente local replica la arquitectura de microservicios de HERA usando Docker Compose:

Entorno de Desarrollo Local — Docker Compose
Capa de Aplicación
frontend Next.js / React :3000
bff-api Node.js / Python :4000
microservicio Java / .NET / Go :8080
Docker Network (red interna)
Capa de Infraestructura (emulada)
postgres PostgreSQL 16 :5432
redis Redis 7 Alpine :6379
pubsub GCP Emulator :8085
rabbitmq RabbitMQ 3 Mgmt :5672 / :15672
Mensaje clave Todos los servicios corren en contenedores aislados. El código se monta vía bind mounts para hot-reload.

Plantillas oficiales: grupo-herdez/platform/stacks/

Sección titulada «Plantillas oficiales: grupo-herdez/platform/stacks/»

Los artefactos de desarrollo local (Dockerfile.dev, docker-compose.yml, docker-compose.override.yml) no se escriben desde cero. El equipo de HERA publica y mantiene un catálogo de plantillas oficiales validadas y aprobadas en:

https://hera.gitlab.cloudherdez.com/grupo-herdez/platform/stacks/

Cada plantilla es el estándar de Grupo Herdez para su stack: base image aprobada, versión de runtime fijada, healthchecks, puerto de debug, convenciones de hot-reload y compatibilidad con el docker-compose.override.yml canónico.

Los equipos de desarrollo pueden elegir el modo que mejor se adapte a su caso:

ModoCuándo usarloCómo funcionaUpdates de HERA
Fork (recomendado)Proyectos nuevos o refactors planificadosClonar el repo de la plantilla desde grupo-herdez/platform/stacks/* y adaptarla en el repositorio del producto. El upstream queda trackeado.Automáticos — MRs de sincronización cuando HERA libera una nueva versión (nueva base image, fix de seguridad, mejora de healthcheck).
Copy-as-referenceAdaptación de un fragmento puntual, onboarding, aprendizaje del patrónCopiar únicamente el fragmento que interesa (ej. un Dockerfile.dev) sin enlazar el repo con el upstream.Manuales — el equipo es responsable de revisar los changelogs de grupo-herdez/platform/stacks/ y mantenerse al día.

A continuación, la composición de la plantilla grupo-herdez/platform/stacks/compose-multiservice para un producto tipo e-commerce con frontend, BFF API, microservicio, base de datos, caché y mensajería.

Estructura de proyecto con Docker Compose

Ejemplo de un producto e-commerce con frontend, BFF API, microservicio y scripts de inicializacion.

Repositorio del Producto

tienda-herdez/
├── docker-compose.yml          ← Orquestacion de todos los servicios
├── docker-compose.override.yml ← Configuracion de desarrollo (hot-reload)
├── .env                        ← Variables de entorno (NO commitear)
├── .env.example                ← Template de variables (SI commitear)
├── frontend-next/
│   ├── Dockerfile
│   ├── Dockerfile.dev          ← Optimizado para desarrollo
│   └── src/
├── bff-api/
│   ├── Dockerfile
│   ├── Dockerfile.dev
│   └── src/
├── checkout-service/
│   ├── Dockerfile
│   ├── Dockerfile.dev
│   └── src/
└── scripts/
    ├── init-db.sql             ← Seed de base de datos
    └── init-pubsub.sh          ← Creacion de topics y suscripciones
Directorio Docker/Compose Config/Scripts Sensible (no commitear)
Mensaje clave Estructura estándar: docker-compose.yml + .env.example + Dockerfile.dev. Hot-reload incluido.

La plantilla base declara la topología completa del stack local: servicios de aplicación + servicios de infraestructura emulados en una red privada.

ServicioPropósitoPuerto expuestoHealthcheck
frontendFrontend Next.js del producto3000— (depende de bff-api)
bff-apiBackend-for-Frontend (Node.js)4000GET /health cada 10 s
checkout-serviceMicroservicio de dominio (Spring Boot)8080Spring Boot Actuator
ServicioImagenPuertoPropósitoPersistencia
postgrespostgres:16-alpine5432Base de datos relacionalVolumen postgres-data
redisredis:7-alpine6379Caché en memoria (LRU, 128 MB)Volumen redis-data
pubsub-emulatorgoogle-cloud-cli8085Emulador de GCP Pub/Sub— (in-memory)
rabbitmqrabbitmq:3-management-alpine5672, 15672Mensajería AMQP + UIVolumen rabbitmq-data
  • Red privada hera-local (bridge) con resolución por nombre de servicio — ningún servicio expone puertos inter-servicio al host.
  • Versiones de imagen fijas (postgres:16-alpine, no :latest) para reproducibilidad entre miembros del equipo.
  • Healthchecks obligatorios en servicios de infraestructura — el depends_on: condition: service_healthy del compose los espera antes de arrancar la aplicación.
  • Credenciales locales estándar (hera / hera_dev) — nunca reutilizar secretos de QA/PRD.

docker-compose.override.yml (desarrollo con hot-reload)

Sección titulada «docker-compose.override.yml (desarrollo con hot-reload)»

El override, incluido en la misma plantilla, aplica solo en desarrollo local (se ignora en CI): añade bind mounts del código fuente para hot-reload sin rebuild, volúmenes nombrados para node_modules que evitan conflictos host/contenedor, y expone el puerto de debug remoto (5005) para el servicio Java.

ServicioBind mountVolumen nombradoComando modificado
frontend./frontend-next/src, ./frontend-next/publicfrontend-modules/app/node_modules— (hereda del base)
bff-api./bff-api/srcbff-modules/app/node_modulesnpm run dev (watch mode)
checkout-service./checkout-service/srcmvnw spring-boot:run con JDWP en 5005

El Dockerfile.dev está optimizado para desarrollo local con hot-reload, a diferencia del Dockerfile de producción que usa Golden Images multi-stage. HERA publica una plantilla oficial por stack bajo grupo-herdez/platform/stacks/; los equipos pueden forkear la plantilla (recomendado) o copiar el código como referencia para proyectos simples.

StackPlantilla oficialBase imagePuertosHot-reload
Node.js (frontend / BFF)grupo-herdez/platform/stacks/nodejsnode:20-alpine3000npm run dev (watch)
Java / Spring Bootgrupo-herdez/platform/stacks/java-springbooteclipse-temurin:21-jdk-alpine8080 + 5005 (debug JDWP)Spring Boot DevTools
Python / FastAPIgrupo-herdez/platform/stacks/python-fastapipython:3.12-slim8000uvicorn --reload
  • Capas de dependencias cacheadas: COPY del manifest de dependencias (package*.json, pom.xml, requirements.txt) antes del resto del código — cambiar una línea de código no invalida la capa de dependencias.
  • Versión de runtime fija: ningún tag mutable (:latest, :lts). Las actualizaciones de runtime llegan como MRs upstream.
  • Compatibilidad con bind mounts: el COPY . . final se sobrescribe por los bind mounts del docker-compose.override.yml, habilitando hot-reload sin rebuild.
  • No son production-ready: los Dockerfile.dev no se usan nunca en PRD. Para producción cada stack tiene su propio Dockerfile multi-stage basado en Golden Images.

Ventana de terminal
# Levantar todos los servicios (con build si es necesario)
docker compose up --build
# Levantar en background (detached)
docker compose up -d
# Ver logs de un servicio específico
docker compose logs -f bff-api
# Detener todos los servicios
docker compose down
# Detener y eliminar volúmenes (reset completo de datos)
docker compose down -v
# Reconstruir un servicio específico sin caché
docker compose build --no-cache bff-api
# Ejecutar un comando dentro de un contenedor en ejecución
docker compose exec bff-api sh
# Ver el estado de los servicios
docker compose ps
Ventana de terminal
# Conectarse a PostgreSQL
docker compose exec postgres psql -U hera -d tienda_herdez
# Importar un dump de base de datos
docker compose exec -T postgres psql -U hera -d tienda_herdez < backup.sql
# Ver logs de la base de datos
docker compose logs postgres
Ventana de terminal
# Crear un topic en el emulador de Pub/Sub
docker compose exec pubsub-emulator \
gcloud pubsub topics create pedidos-creados \
--project=hera-local
# Crear una suscripción
docker compose exec pubsub-emulator \
gcloud pubsub subscriptions create sub-pedidos \
--topic=pedidos-creados \
--project=hera-local
# Acceder al panel de RabbitMQ
# Abrir en navegador: http://localhost:15672
# Usuario: hera / Contraseña: hera_dev

Antes de hacer push al repositorio, es obligatorio escanear las imágenes localmente con Docker Scout. Esto se alinea con el Modelo de Responsabilidad Compartida:

Ventana de terminal
# Construir la imagen de producción (no la de dev)
docker build -t tienda-herdez/bff-api:local ./bff-api
# Escanear vulnerabilidades críticas y altas
docker scout cves tienda-herdez/bff-api:local \
--only-severity critical,high
# Ver recomendaciones de actualización de imagen base
docker scout recommendations tienda-herdez/bff-api:local
# Comparar con la versión anterior
docker scout compare tienda-herdez/bff-api:local \
--to tienda-herdez/bff-api:previous
# Generar SBOM (Software Bill of Materials)
docker scout sbom tienda-herdez/bff-api:local

Hadolint valida las mejores prácticas del Dockerfile antes de construir:

Ventana de terminal
# Instalar Hadolint (una sola vez)
# Linux/macOS:
brew install hadolint
# O como contenedor:
docker pull hadolint/hadolint
# Validar un Dockerfile
hadolint ./bff-api/Dockerfile
# Validar con Docker (sin instalar):
docker run --rm -i hadolint/hadolint < ./bff-api/Dockerfile
# Ejemplo de salida:
# Dockerfile:3 DL3018 warning: Pin versions in apk add
# Dockerfile:7 DL3059 info: Multiple consecutive RUN instructions

PrácticaDetalle
Usar bind mounts solo para código fuenteNo montar node_modules ni carpetas de dependencias compiladas
Usar named volumes para dependenciasfrontend-modules:/app/node_modules evita conflictos host/container
Usar healthchecks en todos los serviciosDocker Compose respeta depends_on: condition: service_healthy
Separar Dockerfile.dev de Dockerfile (producción)El de dev incluye herramientas de debug; el de prod usa Golden Images
En Windows, trabajar dentro de WSL2El filesystem de WSL2 es 10x más rápido que el montaje cross-filesystem
PrácticaDetalle
Nunca usar contraseñas reales en el ambiente localUsar hera_dev o similares; nunca reutilizar secretos de QA/PRD
No commitear .envIncluir .env.example como template
Escanear con Docker Scout antes de pushEjecutar docker scout cves contra la imagen de producción
Validar con Hadolint el Dockerfile de producciónDetectar malas prácticas antes de que lleguen al pipeline
Usar imágenes oficiales de infraestructurapostgres:16-alpine, redis:7-alpine, no builds custom
PrácticaDetalle
Usar docker-compose.override.yml para config de devEl archivo base debe ser válido para CI también
Fijar versiones de imágenes de infraestructurapostgres:16-alpine, no postgres:latest
Documentar el setup en el README.md del proyectoIncluir instrucciones de docker compose up y variables requeridas
Incluir scripts de inicializacióninit-db.sql para seed de datos, init-pubsub.sh para topics