Communitygithub.com

patrones-docker

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

¿Qué es patrones-docker?

Esta skill proporciona una guía completa de mejores prácticas y patrones para trabajar con Docker y Docker Compose en el contexto del desarrollo de software y la automatización de instaladores de CLI. Está diseñada para agentes de IA y desarrolladores que necesitan crear, revisar o depurar configuraciones de contenedores, asegurando que sigan estándares de seguridad, rendimiento y portabilidad. La skill cubre desde configuraciones de desarrollo local con recarga en caliente y volúmenes, hasta configuraciones de producción minimalistas y seguras. Incluye secciones detalladas sobre estrategias de redes personalizadas, gestión de secretos y endurecimiento de Dockerfiles para evitar vulnerabilidades comunes, como la ejecución como root o la inclusión de secretos en las capas de la imagen. Una parte fundamental de la skill se centra en el uso de contenedores como arneses de prueba aislados para instaladores de CLI, donde se definen contratos estrictos de aislamiento para evitar la mutación del repositorio fuente y garantizar pruebas reproducibles en múltiples distribuciones de Linux. Además, se incluyen ejemplos prácticos de comandos de depuración, configuración de redes y patrones para evitar anti-patrones comunes, todo ello con el objetivo de facilitar la creación de pipelines CI/CD robustos y entornos de desarrollo consistentes.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/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 el desarrollo en contenedores.

Docker Compose para Desarrollo Local

Pila Estándar de Aplicaciones Web

# docker-compose.yml
services:
  app:
    build:
      context: .
      target: dev                     # Usa la etapa dev del Dockerfile de múltiples etapas
    ports:
      - "3000:3000"
    volumes:
      - .:/app                        # Montaje enlazado para recarga en caliente
      - /app/node_modules             # Volumen anónimo: conserva 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 email local
    image: axllent/mailpit
    ports:
      - "8025:8025"                   # Interfaz web
      - "1025:1025"                   # SMTP

volumes:
  pgdata:
  redisdata:

Dockerfile para 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 (se carga 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 db
redis://redis:6379/0                             # "redis" resuelve al contenedor 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 host, no desde la red
    # Omitir puertos por completo en producción: accesible solo dentro de la red Docker

Estrategias de Volúmenes

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

  # Montaje enlazado: mapea un directorio del host al contenedor (para desarrollo)
  # - ./src:/app/src

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

Patrones Comunes

services:
  app:
    volumes:
      - .:/app                   # Código fuente (montaje enlazado para recarga en caliente)
      - /app/node_modules        # Protege node_modules del contenedor del host
      - /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 del Contenedor

Endurecimiento del Dockerfile

# 1. Usar 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 hacer commit de .env en git
    environment:
      - API_KEY                  # Hereda del entorno del host

# 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 HACER ESTO

Arnés de Instalación de CLI Reforzado

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

Respetar el Límite de la Plataforma

  • Ejecute 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. Ejecute el mismo punto de entrada de prueba libre de shell de forma nativa en macOS.
  • Los contenedores de Windows requieren un motor Docker de Windows. Ejecute la lógica independiente de la plataforma en un runner de CI de Windows nativo y reserve los contenedores de Windows para un host de Windows.
  • Mantenga una matriz de CI nativa de Ubuntu/macOS/Windows para rutas específicas del host, shims de comandos, comillas y comportamiento del sistema de archivos.

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

Hacer Cumplir el Contrato de Aislamiento

  • Fije las imágenes base por digest inmutable y fije las versiones de CLI instaladas.
  • Ejecute como un UID/GID numérico no root cuando los nombres de cuenta de la distribución difieran.
  • Monte el repositorio y el proyecto fuente como solo lectura.
  • Copie el proyecto fuente en un espacio de trabajo tmpfs escribible antes de cualquier mutación.
  • Monte /workspace con noexec, UID/GID 1000, y mode=0700 para que solo el usuario del contenedor pueda inspeccionar los datos del proyecto.
  • Mantenga 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.
  • Establezca read_only: true, no-new-privileges:true, cap_drop: [ALL], y un pids_limit finito.
  • Mantenga los servicios de CLI reales predeterminados en network_mode: none. Agregue acceso a la red solo a través de un servicio de suscripción opcional con nombre visible para una sesión de proveedor autenticado; nunca lo convierta en un valor predeterminado accidental impulsado por el entorno.
  • Cree solo las rutas temporales escribibles que la herramienta necesita.
  • No pase credenciales del host al contenedor por defecto.
  • Por defecto, realice una ejecución en seco y permita solo los modos explícitos dry-run, install, plugin y shell.
  • Use arreglos de argumentos o spawnSync(..., { shell: false }) para runners multiplataforma. Nunca interpole rutas de proyecto en un comando shell.

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

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

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

Valide el modelo de Compose antes de construir:

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

Construya ambas imágenes de Linux reales:

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

Ejecute el flujo seguro predeterminado 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 a partir del 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 el mapeo bin.ecc de package.json confinado, luego invoca el ejecutable ecc extraído. El tiempo de ejecución permanece en network_mode: none, no ejecuta scripts de ciclo de vida del paquete y no depende de node_modules del host; sus dependencias de producción fijadas exactas 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

Inicie un contenedor separado sin --rm para que al salir de una terminal no se 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. Confirme que se está ejecutando, luego emita el lado Docker del contrato de datos del abridor de terminal v1:

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 de executable y argv (más contractVersion: 1): el ejecutable es docker, y argv comienza con exec, -it y -w. Pase esos datos a la skill del abridor de terminal separada cuando esté instalada. Este arnés de Docker deliberadamente no importa un adaptador de terminal, interpola un comando shell ni gestiona un proceso GUI del host. Hasta entonces, abra la misma PTY en la terminal del host actual directamente:

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

Salga del shell sin detener el contenedor separado. Reconecte con el mismo comando docker exec -it. Cuando termine, elimine el contenedor nombrado exacto y sus recursos del proyecto de 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 host están ausentes por defecto 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 necesita una red, primero construya real-cli y luego opte visiblemente con docker compose --profile networked run real-cli-networked shell. Prefiera autenticarse dentro de esa sesión desechable. Si una ejecución de CI debe heredar una credencial de entorno del host, hágalo optativo en la invocación con una bandera explícita --env NAME de Compose, entienda que el valor es inspeccionable y puede ser exfiltrado durante la vida útil del contenedor, y elimine el contenedor nombrado exacto inmediatamente después.

Ejecute la misma suite enfocada de forma nativa en el host:

npm run test:plugin-setup-platform

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

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

Limpie 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 registros
docker compose logs -f app           # Seguir registros 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 utilizados

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 red
docker network ls
docker network inspect <project>_default

Anti-Patrones

# MAL: Uso de `latest` sin control de versiones
# FROM node:latest

# MAL: Ejecutar como root en producción
# USER root

# MAL: Exponer puertos de base de datos a todo el mundo
# ports:
#   - "0.0.0.0:5432:5432"

# MAL: Hardcodear secretos en variables de entorno del Dockerfile
# ENV DATABASE_URL=postgres://user:password@host:5432/db

# MAL: Montar todo el contexto de build como volumen de desarrollo
# volumes:
#   - .:/app
# (puede sobrescribir node_modules del contenedor)

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/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

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.

Skills relacionados