Communitygithub.com

docker-patterns

Modèles Docker et Docker Compose pour le développement local, des scripts d'installation CLI sécurisés, la sécurité des conteneurs, la mise en réseau, les volumes et l'orchestration multi-services. À utiliser lors de la création ou de la révision de Dockerfiles et de services Compose, du test d'installateurs sur différentes distributions Linux, ou de la planification d'une validation précise sur macOS et Windows natifs.

Qu'est-ce que docker-patterns ?

Ce référentiel de compétences fournit des modèles et des bonnes pratiques éprouvés pour Docker et Docker Compose, spécialement conçus pour le développement local et les pipelines d'installation CLI sécurisés. Il couvre la configuration de piles web standard avec des Dockerfiles multi-étapes, la mise en réseau entre services, la gestion des volumes, et la sécurisation des conteneurs via des directives de réduction de privilèges et de gestion des secrets. Un point central est le module de script d'installation CLI renforcé, qui décrit comment utiliser des conteneurs pour tester les installateurs de manière isolée et reproductible, en respectant les limites des plateformes (Linux, macOS, Windows) et en garantissant qu'aucune mutation n'affecte le dépôt source. La compétence supporte des outils comme Claude Code et intègre des commandes pour la construction, le débogage et le nettoyage des environnements Docker. L'approche privilégie l'isolation réseau, l'exécution en utilisateur non-root, et l'utilisation de fichiers de surcouche (override) pour séparer les configurations de développement et de production.

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

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Modèles Docker

Bonnes pratiques Docker et Docker Compose pour le développement conteneurisé.

Docker Compose pour le Développement Local

Pile d'Application Web Standard

# docker-compose.yml
services:
  app:
    build:
      context: .
      target: dev                     # Utilise l'étape dev du Dockerfile multi-étapes
    ports:
      - "3000:3000"
    volumes:
      - .:/app                        # Montage de liaison pour le rechargement à chaud
      - /app/node_modules             # Volume anonyme -- préserve les dépendances du conteneur
    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:                            # Test d'email local
    image: axllent/mailpit
    ports:
      - "8025:8025"                   # Interface Web
      - "1025:1025"                   # SMTP

volumes:
  pgdata:
  redisdata:

Dockerfile Développement vs Production

# Étape : dépendances
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

# Étape : dev (rechargement à chaud, outils de débogage)
FROM node:22-alpine AS dev
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]

# Étape : 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

# Étape : production (image minimale)
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"]

Fichiers de Surcouche

# docker-compose.override.yml (chargé automatiquement, paramètres de développement uniquement)
services:
  app:
    environment:
      - DEBUG=app:*
      - LOG_LEVEL=debug
    ports:
      - "9229:9229"                   # Débogueur Node.js

# docker-compose.prod.yml (explicite pour la production)
services:
  app:
    build:
      target: production
    restart: always
    deploy:
      resources:
        limits:
          cpus: "1.0"
          memory: 512M
# Développement (charge automatiquement la surcouche)
docker compose up

# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Mise en Réseau

Découverte de Services

Les services dans le même réseau Compose se résolvent par nom de service :

# Depuis le conteneur "app" :
postgres://postgres:postgres@db:5432/app_dev    # "db" se résout en conteneur db
redis://redis:6379/0                             # "redis" se résout en conteneur redis

Réseaux Personnalisés

services:
  frontend:
    networks:
      - frontend-net

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

  db:
    networks:
      - backend-net              # Accessible uniquement depuis api, pas depuis frontend

networks:
  frontend-net:
  backend-net:

N'exposer que le Nécessaire

services:
  db:
    ports:
      - "127.0.0.1:5432:5432"   # Accessible uniquement depuis l'hôte, pas depuis le réseau
    # Omettre complètement les ports en production -- accessible uniquement dans le réseau Docker

Stratégies de Volumes

volumes:
  # Volume nommé : persiste entre les redémarrages de conteneur, géré par Docker
  pgdata:

  # Montage de liaison : mappe un répertoire hôte dans le conteneur (pour le développement)
  # - ./src:/app/src

  # Volume anonyme : préserve le contenu généré par le conteneur du remplacement du montage de liaison
  # - /app/node_modules

Modèles Courants

services:
  app:
    volumes:
      - .:/app                   # Code source (montage de liaison pour rechargement à chaud)
      - /app/node_modules        # Protège le node_modules du conteneur de l'hôte
      - /app/.next               # Protège le cache de build

  db:
    volumes:
      - pgdata:/var/lib/postgresql/data          # Données persistantes
      - ./scripts/init.sql:/docker-entrypoint-initdb.d/init.sql  # Scripts d'initialisation

Sécurité des Conteneurs

Durcissement du Dockerfile

# 1. Utiliser des tags spécifiques (jamais :latest)
FROM node:22.12-alpine3.20

# 2. Exécuter en tant que non-root
RUN addgroup -g 1001 -S app && adduser -S app -u 1001
USER app

# 3. Supprimer les capacités (dans compose)
# 4. Système de fichiers racine en lecture seule lorsque possible
# 5. Pas de secrets dans les couches d'image

Sécurité dans Compose

services:
  app:
    security_opt:
      - no-new-privileges:true
    read_only: true
    tmpfs:
      - /tmp
      - /app/.cache
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE          # Uniquement si vous liez des ports < 1024

Gestion des Secrets

# BON : Utiliser des variables d'environnement (injectées à l'exécution)
services:
  app:
    env_file:
      - .env                     # Ne jamais commit .env dans git
    environment:
      - API_KEY                  # Hérite de l'environnement hôte

# BON : Secrets Docker (mode Swarm)
secrets:
  db_password:
    file: ./secrets/db_password.txt

services:
  db:
    secrets:
      - db_password

# MAUVAIS : Codé en dur dans l'image
# ENV API_KEY=sk-proj-xxxxx      # NE JAMAIS FAIRE CECI

Scripts d'Installation CLI Renforcés

Utilisez des conteneurs pour tester le comportement d'un installateur sur des copies jetables de projet sans permettre au test de modifier la copie source.

Respecter les Limites de la Plateforme

  • Exécutez des conteneurs réels pour les distributions Linux telles que Debian et Ubuntu.
  • macOS ne peut pas s'exécuter en tant que conteneur Docker car Docker partage un noyau Linux. Exécutez le même point d'entrée de test sans shell de manière native sur macOS.
  • Les conteneurs Windows nécessitent un moteur Docker Windows. Exécutez la logique indépendante de la plateforme sur un exécuteur CI Windows natif et réservez les conteneurs Windows pour un hôte Windows.
  • Conservez une matrice CI native Ubuntu/macOS/Windows pour les chemins spécifiques à l'hôte, les shims de commande, les guillemets et le comportement du système de fichiers.

N'affirmez pas qu'un conteneur Linux valide le comportement de macOS ou Windows.

Appliquer le Contrat d'Isolation

  • Épinglez les images de base par empreinte immuable et épinglez les versions CLI installées.
  • Exécutez en tant qu'UID/GID numérique non-root lorsque les noms de comptes de distribution diffèrent.
  • Montez le dépôt et le projet source en lecture seule.
  • Copiez le projet source dans un espace de travail tmpfs accessible en écriture avant toute mutation.
  • Montez /workspace avec noexec, UID/GID 1000, et mode=0700 pour que seul l'utilisateur du conteneur puisse inspecter les données du projet.
  • Conservez le cache exécutable de npm et npx à NPM_CONFIG_CACHE=/tmp/npm-cache sur le montage exécutable /tmp. Sa taille par défaut est de 2 Go et peut être ajustée avec ECC_TMPFS_SIZE ; ECC_WORKSPACE_SIZE contrôle séparément le montage de l'espace de travail privé.
  • Définissez read_only: true, no-new-privileges:true, cap_drop: [ALL], et une pids_limit finie.
  • Conservez les services CLI réels par défaut sur network_mode: none. Ajoutez l'accès réseau uniquement via un service optionnel dont le nom est visible pour une session de fournisseur authentifié ; n'en faites jamais une valeur par défaut accidentelle dictée par l'environnement.
  • Créez uniquement les chemins temporaires accessibles en écriture dont l'outil a besoin.
  • Ne transmettez pas les identifiants de l'hôte dans le conteneur par défaut.
  • Par défaut, effectuez un essai à blanc et autorisez uniquement les modes explicites dry-run, install, plugin et shell.
  • Utilisez des tableaux d'arguments ou spawnSync(..., { shell: false }) pour les exécuteurs multiplateformes. N'interpolez jamais les chemins de projet dans une commande shell.

Exercer le Harness de Configuration du Plugin ECC

Utilisez docker/plugin-setup/compose.yaml comme implémentation de référence. Il fournit :

  • fixture-tests pour la suite ciblée de manifeste d'installation, de cible et d'exécuteur.
  • real-cli pour l'image Linux générique basée sur Debian épinglée.
  • real-cli-ubuntu pour l'image Ubuntu épinglée.

Validez le modèle Compose avant la construction :

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

Construisez les deux images Linux réelles :

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

Exécutez le flux par défaut sécurisé dans chaque image :

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

L'essai à blanc exécute le contrat de commande publique actuel :

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

Avant l'exécution de cette commande, le conteneur crée un artefact npm empaqueté localement à partir de la copie source en lecture seule avec npm pack --ignore-scripts. Il extrait l'archive auto-créée sous /tmp, valide le nom du paquet ecc-universal, les manifestes d'installation requis et le mappage bin.ecc confiné dans package.json, puis invoque l'exécutable ecc extrait. L'environnement d'exécution reste sur network_mode: none, n'exécute pas les scripts de cycle de vie du paquet et ne dépend pas des node_modules de l'hôte ; ses dépendances de production épinglées exactes sont déjà présentes dans l'image.

Le harness rejette un plan vide, une cible autre que claude-project, toute opération en dehors de /workspace/project/.claude, ou tout essai à blanc qui crée le répertoire cible. install effectue l'application isolée deux fois, vérifie son état d'installation gérée, liste la cible installée et exécute doctor.

Démarrer, Ouvrir, Reconnecter et Nettoyer une Session Nommée

Démarrez un conteneur détaché sans --rm pour que quitter un terminal ne supprime pas la session :

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

Le conteneur copie l'élément de test en lecture seule dans le répertoire privé stable /workspace/project. Confirmez qu'il est en cours d'exécution, puis émettez la partie Docker du contrat de données v1 de l'ouvreur 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

Le résultat JSON a exactement une limite executable et argv (plus contractVersion: 1) : l'exécutable est docker, et argv commence par exec, -it et -w. Transmettez ces données à la compétence d'ouvreur de terminal séparée lorsqu'elle est installée. Ce harness Docker n'importe délibérément pas d'adaptateur de terminal, n'interpole pas de commande shell et ne gère pas de processus GUI hôte. Jusque-là, ouvrez le même PTY dans le terminal hôte actuel directement :

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

Quittez le shell sans arrêter le conteneur détaché. Reconnectez-vous avec la même commande docker exec -it. Lorsque vous avez terminé, supprimez le conteneur nommé exact et ses ressources du projet Compose :

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

Les identifiants de l'hôte sont absents par défaut et les répertoires d'identifiants ne sont jamais montés. Le service par défaut n'a également aucun accès réseau. Lorsqu'une session de fournisseur authentifié a réellement besoin d'un réseau, construisez real-cli d'abord, puis optez-y visiblement avec docker compose --profile networked run real-cli-networked shell. Préférez l'authentification à l'intérieur de cette session jetable. Si une exécution CI doit hériter d'un identifiant d'environnement hôte, rendez cette option explicite à l'invocation avec un indicateur explicite --env NAME de Compose, sachez que la valeur est inspectable et peut être exfiltrée pendant la durée de vie du conteneur, et supprimez le conteneur nommé exact immédiatement après.

Exécutez la même suite ciblée de manière native sur l'hôte :

npm run test:plugin-setup-platform

Inspectez l'identité et l'environnement produits avant de faire confiance à l'image :

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

Nettoyez chaque projet de test nommé sans supprimer les volumes ou images non liés :

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/

Débogage

Commandes Courantes

# Afficher les logs
docker compose logs -f app           # Suivre les logs de app
docker compose logs --tail=50 db     # Dernières 50 lignes de db

# Exécuter des commandes dans un conteneur en cours d'exécution
docker compose exec app sh           # Shell dans app
docker compose exec db psql -U postgres  # Se connecter à postgres

# Inspecter
docker compose ps                     # Services en cours d'exécution
docker compose top                    # Processus dans chaque conteneur
docker stats                          # Utilisation des ressources

# Reconstruire
docker compose up --build             # Reconstruire les images
docker compose build --no-cache app   # Forcer une reconstruction complète

# Nettoyer
docker compose down                   # Arrêter et supprimer les conteneurs
docker compose down -v                # Supprimer également les volumes (DESTRUCTEUR)
docker system prune                   # Supprimer les images/conteneurs inutilisés

Débogage des Problèmes Réseau

# Vérifier la résolution DNS à l'intérieur du conteneur
docker compose exec app nslookup db

# Vérifier la connectivité
docker compose exec app wget -qO- http://api:3000/health

# Inspecter le réseau
docker network ls
docker network inspect <projet>_default

Anti-Patterns

# MAUVAIS : Utiliser `:latest`
# FROM node:latest   # Peut casser à tout moment
# Bon : Épinglez les versions
FROM node:22.12-alpine3.20

# MAUVAIS : Exécuter en tant que root
# USER root défaut -- évitez
# Bon : Créez et utilisez un utilisateur non-root
RUN addgroup -g 1001 -S apprun && adduser -S apprun -u 1001
USER apprun

# MAUVAIS : Stocker des secrets dans l'image
# ENV DB_PASSWORD=supersecret   # Exposé dans l'historique des couches
# Bon : Utiliser des variables d'environnement injectées à l'exécution
# docker run -e DB_PASSWORD=...

# MAUVAIS : Utiliser des ports sans restrictions
# ports:
#   - "5432:5432"   # Accessible depuis n'importe où
# Bon : Restreindre à l'hôte local
# ports:
#   - "127.0.0.1:5432:5432"

# MAUVAIS : Ignorer les healthchecks
# Bon : Ajouter des healthchecks pour la fiabilité
# healthcheck:
#   test: ["CMD", "pg_isready", "-U", "postgres"]

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 associés