Communitygithub.com

patrones-docker

Patrones de Docker y Docker Compose para desarrollo local, instaladores CLI reforzados, seguridad de contenedores, redes, volúmenes y orquestación de múltiples servicios. Útil al crear o revisar Dockerfiles y servicios de Compose, probar instaladores en distintas distribuciones de Linux o planificar validaciones precisas en macOS y Windows nativos.

¿Qué es patrones-docker?

Esta habilidad proporciona una guía completa de mejores prácticas y patrones para trabajar con Docker y Docker Compose en entornos de desarrollo, pruebas de instaladores y orquestación de servicios. Cubre configuraciones de desarrollo local con volúmenes de montaje bind, recarga en caliente y dependencias de servicios saludables, así como Dockerfile multietapa para separar entornos de desarrollo y producción. Incluye estrategias avanzadas de redes, como redes personalizadas y exposición controlada de puertos, y patrones de volúmenes para persistencia de datos y protección de dependencias. Además, detalla prácticas de seguridad como ejecución como usuario no root, eliminación de capacidades y gestión de secretos, y un arnés de pruebas reforzado para instaladores CLI que aísla las mutaciones del proyecto fuente mediante contenedores con montajes de solo lectura, tmpfs y sin red. Finalmente, aborda anti-patrones comunes y proporciona comandos útiles para depuración, inspección y limpieza de recursos.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/docker-patterns

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Patrones de Docker

Mejores prácticas de Docker y Docker Compose para desarrollo containerizado.

Docker Compose para Desarrollo Local

Pila Estándar de Aplicación Web

# docker-compose.yml
services:
  app:
    build:
      context: .
      target: dev                     # Usa la etapa dev del Dockerfile multietapa
    ports:
      - "3000:3000"
    volumes:
      - .:/app                        # Montaje bind para recarga en caliente
      - /app/node_modules             # Volumen anónimo -- preserva las dependencias del contenedor
    environment:
      - DATABASE_URL=postgres://postgres:postgres@db:5432/app_dev
      - REDIS_URL=redis://redis:6379/0
      - NODE_ENV=development
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    command: npm run dev

  db:
    image: postgres:16-alpine
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: app_dev
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init.sql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redisdata:/data

  mailpit:                            # Pruebas de correo local
    image: axllent/mailpit
    ports:
      - "8025:8025"                   # Interfaz web
      - "1025:1025"                   # SMTP

volumes:
  pgdata:
  redisdata:

Dockerfile de Desarrollo vs Producción

# Etapa: dependencias
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

# Etapa: dev (recarga en caliente, herramientas de depuración)
FROM node:22-alpine AS dev
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]

# Etapa: build
FROM node:22-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build && npm prune --production

# Etapa: producción (imagen mínima)
FROM node:22-alpine AS production
WORKDIR /app
RUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001
USER appuser
COPY --from=build --chown=appuser:appgroup /app/dist ./dist
COPY --from=build --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=build --chown=appuser:appgroup /app/package.json ./
ENV NODE_ENV=production
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "dist/server.js"]

Archivos de Anulación

# docker-compose.override.yml (cargado automáticamente, solo para desarrollo)
services:
  app:
    environment:
      - DEBUG=app:*
      - LOG_LEVEL=debug
    ports:
      - "9229:9229"                   # Depurador de Node.js

# docker-compose.prod.yml (explícito para producción)
services:
  app:
    build:
      target: production
    restart: always
    deploy:
      resources:
        limits:
          cpus: "1.0"
          memory: 512M
# Desarrollo (carga automática de anulación)
docker compose up

# Producción
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Redes

Descubrimiento de Servicios

Los servicios en la misma red de Compose se resuelven por nombre de servicio:

# Desde el contenedor "app":
postgres://postgres:postgres@db:5432/app_dev    # "db" resuelve al contenedor de base de datos
redis://redis:6379/0                             # "redis" resuelve al contenedor de redis

Redes Personalizadas

services:
  frontend:
    networks:
      - frontend-net

  api:
    networks:
      - frontend-net
      - backend-net

  db:
    networks:
      - backend-net              # Solo accesible desde api, no desde frontend

networks:
  frontend-net:
  backend-net:

Exponer Solo lo Necesario

services:
  db:
    ports:
      - "127.0.0.1:5432:5432"   # Solo accesible desde el anfitrión, no desde la red
    # Omitir puertos por completo en producción -- accesible solo dentro de la red Docker

Estrategias de Volúmenes

volumes:
  # Volumen nombrado: persiste entre reinicios del contenedor, gestionado por Docker
  pgdata:

  # Montaje bind: asigna un directorio del anfitrión al contenedor (para desarrollo)
  # - ./src:/app/src

  # Volumen anónimo: preserva el contenido generado por el contenedor de la anulación del montaje bind
  # - /app/node_modules

Patrones Comunes

services:
  app:
    volumes:
      - .:/app                   # Código fuente (montaje bind para recarga en caliente)
      - /app/node_modules        # Protege el node_modules del contenedor del anfitrión
      - /app/.next               # Protege la caché de build

  db:
    volumes:
      - pgdata:/var/lib/postgresql/data          # Datos persistentes
      - ./scripts/init.sql:/docker-entrypoint-initdb.d/init.sql  # Scripts de inicialización

Seguridad de Contenedores

Endurecimiento de Dockerfile

# 1. Usa etiquetas específicas (nunca :latest)
FROM node:22.12-alpine3.20

# 2. Ejecutar como no root
RUN addgroup -g 1001 -S app && adduser -S app -u 1001
USER app

# 3. Eliminar capacidades (en compose)
# 4. Sistema de archivos raíz de solo lectura cuando sea posible
# 5. Sin secretos en las capas de la imagen

Seguridad en Compose

services:
  app:
    security_opt:
      - no-new-privileges:true
    read_only: true
    tmpfs:
      - /tmp
      - /app/.cache
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE          # Solo si se enlazan puertos < 1024

Gestión de Secretos

# BIEN: Usar variables de entorno (inyectadas en tiempo de ejecución)
services:
  app:
    env_file:
      - .env                     # Nunca subir .env a git
    environment:
      - API_KEY                  # Hereda del entorno del anfitrión

# BIEN: Secretos de Docker (modo Swarm)
secrets:
  db_password:
    file: ./secrets/db_password.txt

services:
  db:
    secrets:
      - db_password

# MAL: Hardcodeado en la imagen
# ENV API_KEY=sk-proj-xxxxx      # NUNCA HAGAS ESTO

Arnés de Instaladores CLI Reforzados

Utiliza contenedores para probar el comportamiento del instalador con copias desechables del proyecto sin permitir que la prueba modifique el checkout fuente.

Respeta el Límite de la Plataforma

  • Ejecuta contenedores reales para distribuciones de Linux como Debian y Ubuntu.
  • macOS no puede ejecutarse como un contenedor Docker porque Docker comparte un kernel de Linux. Ejecuta el mismo punto de entrada de prueba sin shell de forma nativa en macOS.
  • Los contenedores de Windows requieren un motor Docker de Windows. Ejecuta la lógica independiente de la plataforma en un runner de CI nativo de Windows y reserva los contenedores de Windows para un anfitrión Windows.
  • Mantén una matriz nativa de CI para Ubuntu/macOS/Windows para rutas específicas del anfitrión, shims de comandos, comillas y comportamiento del sistema de archivos.

No afirmes que un contenedor Linux valida el comportamiento de macOS o Windows.

Aplica el Contrato de Aislamiento

  • Fija las imágenes base por digest inmutable y fija las versiones de CLI instaladas.
  • Ejecuta como UID/GID numérico no root cuando los nombres de cuentas de las distribuciones difieren.
  • Monta el repositorio y el proyecto fuente como solo lectura.
  • Copia el proyecto fuente en un espacio de trabajo tmpfs escribible antes de cualquier mutación.
  • Monta /workspace con noexec, UID/GID 1000 y mode=0700 para que solo el usuario del contenedor pueda inspeccionar los datos del proyecto.
  • Mantén la caché ejecutable de npm y npx en NPM_CONFIG_CACHE=/tmp/npm-cache en el montaje ejecutable /tmp. Su tamaño predeterminado es 2 GiB y se puede ajustar con ECC_TMPFS_SIZE; ECC_WORKSPACE_SIZE controla por separado el montaje del espacio de trabajo privado.
  • Establece read_only: true, no-new-privileges:true, cap_drop: [ALL] y un pids_limit finito.
  • Mantén los servicios CLI reales predeterminados en network_mode: none. Agrega acceso a la red solo a través de un servicio opt-in con nombre visible para una sesión de proveedor autenticado; nunca lo conviertas en un valor predeterminado accidental impulsado por el entorno.
  • Crea solo las rutas temporales escribibles que la herramienta necesita.
  • No pases credenciales del anfitrión al contenedor de forma predeterminada.
  • Por defecto, usa una ejecución en seco y permite solo los modos explícitos dry-run, install, plugin y shell.
  • Usa arreglos de argumentos o spawnSync(..., { shell: false }) para ejecutores multiplataforma. Nunca interpoles rutas de proyecto en un comando shell.

Ejercita el Arnés de Configuración del Plugin ECC

Usa docker/plugin-setup/compose.yaml como la implementación de referencia. Proporciona:

  • fixture-tests para el suite de manifiesto de instalación, destino y ejecutor enfocado.
  • real-cli para la imagen Linux genérica basada en Debian fijada.
  • real-cli-ubuntu para la imagen Ubuntu fijada.

Valida el modelo de Compose antes de construir:

docker compose -f docker/plugin-setup/compose.yaml config --quiet

Construye ambas imágenes Linux reales:

docker compose -f docker/plugin-setup/compose.yaml \
  build real-cli real-cli-ubuntu

Ejecuta el flujo predeterminado seguro en cada imagen:

docker compose -p ecc-plugin-debian-test \
  -f docker/plugin-setup/compose.yaml \
  run --rm -T real-cli dry-run

docker compose -p ecc-plugin-ubuntu-test \
  -f docker/plugin-setup/compose.yaml \
  run --rm -T real-cli-ubuntu dry-run

La ejecución en seco ejecuta el contrato de comando público actual:

ecc install --profile core --target claude-project --dry-run --json

Antes de que se ejecute ese comando, el contenedor crea un artefacto npm empaquetado localmente desde el checkout de solo lectura con npm pack --ignore-scripts. Extrae el tarball auto-creado en /tmp, valida el nombre del paquete ecc-universal, los manifiestos de instalación requeridos y la asignación package.json bin.ecc confinada, luego invoca el ejecutable ecc extraído. El tiempo de ejecución permanece en network_mode: none, no ejecuta scripts del ciclo de vida del paquete y no depende de los node_modules del anfitrión; sus dependencias de producción exactas fijadas ya están presentes en la imagen.

El arnés rechaza un plan vacío, un destino que no sea claude-project, cualquier operación fuera de /workspace/project/.claude o cualquier ejecución en seco que cree el directorio de destino. install realiza la aplicación aislada dos veces, verifica su estado de instalación gestionado, lista el destino instalado y ejecuta doctor.

Iniciar, Abrir, Reconectar y Limpiar una Sesión Nombrada

Inicia un contenedor separado sin --rm para que salir de un terminal no elimine la sesión:

docker compose -p ecc-plugin-session \
  -f docker/plugin-setup/compose.yaml \
  run --detach --name ecc-plugin-shell real-cli shell

El contenedor copia el fixture de solo lectura al directorio privado estable /workspace/project. Confirma que se está ejecutando y luego emite el contrato de datos v1 del lado Docker del abridor de terminal:

docker inspect --format '{{.State.Running}}' ecc-plugin-shell
node docker/plugin-setup/interactive-plan.js \
  --container ecc-plugin-shell \
  --workdir /workspace/project \
  --json \
  -- bash

El resultado JSON tiene exactamente un límite executable y argv (más contractVersion: 1): el ejecutable es docker, y argv comienza con exec, -it y -w. Pasa esos datos a la habilidad separada de abridor de terminal cuando esté instalada. Este arnés Docker deliberadamente no importa un adaptador de terminal, interpola un comando shell ni gestiona un proceso GUI del anfitrión. Hasta entonces, abre el mismo PTY en el terminal del anfitrión actual directamente:

docker exec -it -w /workspace/project ecc-plugin-shell bash

Sal del shell sin detener el contenedor separado. Reconecta con el mismo comando docker exec -it. Cuando termines, elimina el contenedor nombrado exacto y sus recursos del proyecto Compose:

docker rm --force ecc-plugin-shell
docker compose -p ecc-plugin-session \
  -f docker/plugin-setup/compose.yaml \
  down --remove-orphans

Las credenciales del anfitrión están ausentes de forma predeterminada y los directorios de credenciales nunca se montan. El servicio predeterminado tampoco tiene acceso a la red. Cuando una sesión de proveedor autenticado realmente necesite una red, construye real-cli primero y luego haz opt-in visiblemente con docker compose --profile networked run real-cli-networked shell. Prefiere autenticar dentro de esa sesión desechable. Si una ejecución de CI debe heredar una credencial de entorno del anfitrión, haz que ese opt-in sea en la invocación con una bandera explícita --env NAME de Compose, entiende que el valor es inspeccionable y puede ser exfiltrado durante la vida útil del contenedor, y elimina el contenedor nombrado exacto inmediatamente después.

Ejecuta el mismo suite enfocado de forma nativa en el anfitrión:

npm run test:plugin-setup-platform

Inspecciona la identidad y el entorno producidos antes de confiar en la imagen:

docker image inspect ecc-plugin-setup:debian ecc-plugin-setup:ubuntu

Limpia cada proyecto de prueba nombrado sin eliminar volúmenes o imágenes no relacionados:

docker compose -p ecc-plugin-debian-test \
  -f docker/plugin-setup/compose.yaml down --remove-orphans
docker compose -p ecc-plugin-ubuntu-test \
  -f docker/plugin-setup/compose.yaml down --remove-orphans

.dockerignore

node_modules
.git
.env
.env.*
dist
coverage
*.log
.next
.cache
docker-compose*.yml
Dockerfile*
README.md
tests/

Depuración

Comandos Comunes

# Ver logs
docker compose logs -f app           # Seguir logs de app
docker compose logs --tail=50 db     # Últimas 50 líneas de db

# Ejecutar comandos en un contenedor en ejecución
docker compose exec app sh           # Shell dentro de app
docker compose exec db psql -U postgres  # Conectar a postgres

# Inspeccionar
docker compose ps                     # Servicios en ejecución
docker compose top                    # Procesos en cada contenedor
docker stats                          # Uso de recursos

# Reconstruir
docker compose up --build             # Reconstruir imágenes
docker compose build --no-cache app   # Forzar reconstrucción completa

# Limpiar
docker compose down                   # Detener y eliminar contenedores
docker compose down -v                # También eliminar volúmenes (DESTRUCTIVO)
docker system prune                   # Eliminar imágenes/contenedores no usados

Depuración de Problemas de Red

# Verificar resolución DNS dentro del contenedor
docker compose exec app nslookup db

# Verificar conectividad
docker compose exec app wget -qO- http://api:3000/health

# Inspeccionar la red
docker network ls
docker network inspect <project>_default

Anti-Patrones

# MAL: Usar :latest en imágenes base
FROM node:latest

# MAL: Ejecutar como root
USER root

# MAL: Almacenar secretos en variables de entorno en la imagen
ENV API_KEY=sk-proj-xxxxx

# MAL: Exponer puertos de base de datos a 0.0.0.0 en producción
ports:
  - "5432:5432"

# MAL: No usar healthchecks en servicios dependientes
depends_on:
  - db

Prácticas Recomendadas

Dockerfile

  • Usa imágenes base oficiales y ligeras (alpine, slim).
  • Fija versiones específicas de imagen; nunca uses :latest.
  • Usa builds multietapa para minimizar el tamaño de la imagen final.
  • Ejecuta aplicaciones como un usuario no root.
  • Usa COPY en lugar de ADD a menos que necesites descargas de URLs o extracción automática de tarballs.
  • Combina RUN layers para reducir el número de capas.
  • Usa --no-cache o --no-install-recommends para reducir el tamaño de la imagen.
  • Añade HEALTHCHECK a la imagen de producción.

Docker Compose

  • Usa depends_on con condition: service_healthy para servicios con healthcheck.
  • Limita los recursos del contenedor con deploy.resources.limits en producción.
  • Usa archivos .env para configuraciones específicas del entorno.
  • Usa perfiles de Compose para diferentes escenarios (desarrollo, pruebas, producción).
  • Mantén los datos persistentes en volúmenes nombrados.
  • Usa restart: always o restart: unless-stopped para servicios de producción.

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

Skills relacionados