Communitygithub.com

docker-patterns

Docker- und Docker-Compose-Muster für lokale Entwicklung, gehärtete CLI-Installations-Testumgebungen, Containersicherheit, Netzwerke, Volumes und Multi-Service-Orchestrierung.

Was ist docker-patterns?

Diese Skill bietet eine umfassende Sammlung von Best Practices und Mustern für Docker und Docker Compose, die Entwicklern und KI-Agenten bei der Erstellung und Überprüfung von Dockerfiles und Compose-Diensten helfen. Sie unterstützt die lokale Entwicklung durch standardisierte Web-App-Stacks, Development- vs. Production-Dockerfiles und Override-Dateien. Darüber hinaus enthält sie detaillierte Anleitungen zu erweiterten Themen wie benutzerdefinierten Netzwerken, Volume-Strategien und Containersicherheit, einschließlich gehärteter Dockerfiles und Compose-Sicherheitseinstellungen. Ein besonderer Schwerpunkt liegt auf gehärteten CLI-Installations-Testumgebungen, die sicherstellen, dass Installationsskripte zuverlässig in isolierten Containern getestet werden, ohne den Quellcode zu verändern. Die Skill behandelt auch plattformspezifische Validierungen für Linux, macOS und Windows. Sie ist für Plattformen wie Claude Code, Cursor und Codex konzipiert und wird direkt über SKILL.md referenziert, sodass der Agent sofort auf die Muster zugreifen kann, wenn Docker-bezogene Aufgaben anstehen.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/docker-patterns

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Docker Patterns

Best Practices für Docker und Docker Compose in der containerisierten Entwicklung.

Docker Compose für die lokale Entwicklung

Standard-Web-App-Stack

# docker-compose.yml
services:
  app:
    build:
      context: .
      target: dev                     # Verwende dev-Stufe des Multi-Stage-Dockerfiles
    ports:
      - "3000:3000"
    volumes:
      - .:/app                        # Bind-Mount für Hot-Reload
      - /app/node_modules             # Anonymes Volume – bewahrt Container-Abhängigkeiten
    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:                            # Lokales E-Mail-Testing
    image: axllent/mailpit
    ports:
      - "8025:8025"                   # Web-UI
      - "1025:1025"                   # SMTP

volumes:
  pgdata:
  redisdata:

Dockerfile für Entwicklung vs. Produktion

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

# Stage: dev (Hot-Reload, Debug-Tools)
FROM node:22-alpine AS dev
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]

# Stage: 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

# Stage: production (minimales Image)
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"]

Override-Dateien

# docker-compose.override.yml (automatisch geladen, Nur-Entwicklung-Einstellungen)
services:
  app:
    environment:
      - DEBUG=app:*
      - LOG_LEVEL=debug
    ports:
      - "9229:9229"                   # Node.js-Debugger

# docker-compose.prod.yml (explizit für Produktion)
services:
  app:
    build:
      target: production
    restart: always
    deploy:
      resources:
        limits:
          cpus: "1.0"
          memory: 512M
# Entwicklung (lädt automatisch Override)
docker compose up

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

Netzwerke

Service-Discovery

Dienste im selben Compose-Netzwerk werden über den Dienstnamen aufgelöst:

# Vom „app“-Container:
postgres://postgres:postgres@db:5432/app_dev    # „db“ wird zum db-Container aufgelöst
redis://redis:6379/0                             # „redis“ wird zum redis-Container aufgelöst

Benutzerdefinierte Netzwerke

services:
  frontend:
    networks:
      - frontend-net

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

  db:
    networks:
      - backend-net              # Nur von api erreichbar, nicht von frontend

networks:
  frontend-net:
  backend-net:

Nur das Nötigste freigeben

services:
  db:
    ports:
      - "127.0.0.1:5432:5432"   # Nur vom Host aus zugänglich, nicht aus dem Netzwerk
    # Ports in der Produktion vollständig weglassen – nur innerhalb des Docker-Netzwerks zugänglich

Volume-Strategien

volumes:
  # Benanntes Volume: bleibt über Container-Neustarts hinweg erhalten, von Docker verwaltet
  pgdata:

  # Bind-Mount: bildet Host-Verzeichnis in den Container ab (für Entwicklung)
  # - ./src:/app/src

  # Anonymes Volume: bewahrt container-generierte Inhalte vor Überschreibung durch Bind-Mount
  # - /app/node_modules

Häufige Muster

services:
  app:
    volumes:
      - .:/app                   # Quellcode (Bind-Mount für Hot-Reload)
      - /app/node_modules        # Schützt das node_modules des Containers vor dem Host
      - /app/.next               # Schützt den Build-Cache

  db:
    volumes:
      - pgdata:/var/lib/postgresql/data          # Dauerhafte Daten
      - ./scripts/init.sql:/docker-entrypoint-initdb.d/init.sql  # Initialisierungs-Skripte

Containersicherheit

Dockerfile-Härtung

# 1. Bestimmte Tags verwenden (niemals :latest)
FROM node:22.12-alpine3.20

# 2. Als Nicht-Root ausführen
RUN addgroup -g 1001 -S app && adduser -S app -u 1001
USER app

# 3. Capabilities entfernen (in Compose)
# 4. Nur-Lese-Root-Dateisystem, wo möglich
# 5. Keine Geheimnisse in Image-Layern

Compose-Sicherheit

services:
  app:
    security_opt:
      - no-new-privileges:true
    read_only: true
    tmpfs:
      - /tmp
      - /app/.cache
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE          # Nur beim Binden an Ports < 1024

Geheimnisverwaltung

# GUT: Umgebungsvariablen verwenden (zur Laufzeit injiziert)
services:
  app:
    env_file:
      - .env                     # .env niemals in Git committen
    environment:
      - API_KEY                  # Wird von der Host-Umgebung geerbt

# GUT: Docker-Secrets (Swarm-Modus)
secrets:
  db_password:
    file: ./secrets/db_password.txt

services:
  db:
    secrets:
      - db_password

# SCHLECHT: Hartcodiert im Image
# ENV API_KEY=sk-proj-xxxxx      # NIEMALS SO MACHEN

Gehärtete CLI-Installations-Testumgebungen

Verwenden Sie Container, um das Installationsverhalten anhand von wegwerfbaren Projektkopien zu testen, ohne dass der Test das Quell-Checkout verändert.

Die Plattformgrenze respektieren

  • Führen Sie echte Container für Linux-Distributionen wie Debian und Ubuntu aus.
  • macOS kann nicht als Docker-Container ausgeführt werden, da Docker einen Linux-Kernel teilt. Führen Sie den selben shell-freien Test-Einstiegspunkt nativ auf macOS aus.
  • Windows-Container erfordern eine Windows-Docker-Engine. Führen Sie plattformunabhängige Logik auf einem nativen Windows-CI-Runner aus und reservieren Sie Windows-Container für einen Windows-Host.
  • Behalten Sie eine native Ubuntu/macOS/Windows-CI-Matrix für hostspezifische Pfade, Befehlsshims, Zitierung und Dateisystemverhalten bei.

Behaupten Sie nicht, dass ein Linux-Container das Verhalten von macOS oder Windows validiert.

Den Isolationsvertrag durchsetzen

  • Basis-Images per unveränderlichem Digest festlegen und installierte CLI-Versionen festlegen.
  • Als nicht privilegierte numerische UID/GID ausführen, wenn sich die Kontonamen der Distributionen unterscheiden.
  • Das Repository und das Quellprojekt schreibgeschützt einbinden.
  • Das Quellprojekt vor jeder Änderung in einen beschreibbaren tmpfs-Arbeitsbereich kopieren.
  • /workspace mit noexec, UID/GID 1000 und mode=0700 einbinden, sodass nur der Container-Benutzer Projektdaten einsehen kann.
  • Den ausführbaren Cache von npm und npx unter NPM_CONFIG_CACHE=/tmp/npm-cache auf dem ausführbaren /tmp-Mount belassen. Seine Standardgröße beträgt 2 GiB und kann mit ECC_TMPFS_SIZE angepasst werden; ECC_WORKSPACE_SIZE steuert separat den privaten Workspace-Mount.
  • read_only: true, no-new-privileges:true, cap_drop: [ALL] und ein endliches pids_limit setzen.
  • Die standardmäßigen realen CLI-Dienste auf network_mode: none belassen. Netzwerkzugriff nur über einen sichtbar benannten Opt-in-Dienst für eine authentifizierte Anbietersitzung bereitstellen; niemals als versehentlichen, umgebungsgesteuerten Standard.
  • Nur die temporären Schreibpfade erstellen, die das Werkzeug benötigt.
  • Standardmäßig keine Host-Anmeldeinformationen in den Container übergeben.
  • Standardmäßig einen Trockenlauf durchführen und nur die expliziten Modi dry-run, install, plugin und shell zulassen.
  • Argument-Arrays oder spawnSync(..., { shell: false }) für plattformübergreifende Runner verwenden. Projektpfade niemals in einen Shell-Befehl interpolieren.

Das ECC-Plugin-Setup-Harness verwenden

Verwenden Sie docker/plugin-setup/compose.yaml als Referenzimplementierung. Es bietet:

  • fixture-tests für die fokussierte Installationsmanifest-, Ziel- und Ausführersuite.
  • real-cli für das festgelegte Debian-basierte generische Linux-Image.
  • real-cli-ubuntu für das festgelegte Ubuntu-Image.

Validieren Sie das Compose-Modell vor dem Bauen:

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

Beide Linux-Images bauen:

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

Den sicheren Standardablauf in jedem Image ausführen:

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

Der Trockenlauf führt den aktuellen öffentlichen Befehlsvertrag aus:

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

Bevor dieser Befehl ausgeführt wird, erstellt der Container ein lokal gepacktes npm-Artefakt aus dem schreibgeschützten Checkout mit npm pack --ignore-scripts. Er extrahiert das selbsterstellte Tarball unter /tmp, validiert den Paketnamen ecc-universal, erforderliche Installationsmanifeste und die eingeschränkte package.json-bin.ecc-Zuordnung, und ruft dann die extrahierte ecc-ausführbare Datei auf. Die Laufzeit bleibt auf network_mode: none, führt keine Paket-Lebenszyklus-Skripte aus und verlässt sich nicht auf node_modules des Hosts; seine genauen, festgelegten Produktionsabhängigkeiten sind bereits im Image vorhanden.

Das Harness lehnt einen leeren Plan, ein nicht-claude-project-Ziel, jeden Vorgang außerhalb von /workspace/project/.claude oder jeden Trockenlauf ab, der das Zielverzeichnis erstellt. install führt die isolierte Anwendung zweimal aus, überprüft seinen verwalteten Installationsstatus, listet das installierte Ziel auf und führt doctor aus.

Eine benannte Sitzung starten, öffnen, wieder verbinden und bereinigen

Einen Container im abgetrennten (detached) Modus ohne --rm starten, damit das Verlassen des Terminals die Sitzung nicht entfernt:

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

Der Container kopiert die schreibgeschützte Fixture in das stabile private Verzeichnis /workspace/project. Bestätigen Sie, dass er läuft, und geben Sie dann die Docker-Seite des data-Vertrags des Terminal-Öffners v1 aus:

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

Das JSON-Ergebnis hat genau eine executable- und argv-Grenze (plus contractVersion: 1): Die ausführbare Datei ist docker, und argv beginnt mit exec, -it und -w. Übergeben Sie diese Daten an die separate Terminal-Öffner-Skill, wenn sie installiert ist. Dieses Docker-Harness importiert bewusst keinen Terminal-Adapter, interpoliert keinen Shell-Befehl und verwaltet keinen Host-GUI-Prozess. Bis dahin öffnen Sie das selbe PTY direkt im aktuellen Host-Terminal:

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

Verlassen Sie die Shell, ohne den abgetrennten Container zu stoppen. Mit dem selben docker exec -it-Befehl wieder verbinden. Wenn Sie fertig sind, entfernen Sie den genauen benannten Container und seine Compose-Projektressourcen:

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

Host-Anmeldeinformationen sind standardmäßig nicht vorhanden und Anmeldeinformationsverzeichnisse werden niemals eingebunden. Der Standarddienst hat auch keinen Netzwerkzugriff. Wenn eine authentifizierte Anbietersitzung tatsächlich ein Netzwerk benötigt, erstellen Sie real-cli zuerst und entscheiden Sie sich dann sichtbar mit docker compose --profile networked run real-cli-networked shell. Bevorzugen Sie die Authentifizierung innerhalb dieser wegwerfbaren Sitzung. Wenn ein CI-Durchlauf eine Host-Umgebungsanmeldung erben muss, machen Sie diesen Opt-In beim Aufruf mit einem expliziten Compose---env NAME-Flag, verstehen Sie, dass der Wert einsehbar ist und für die Lebensdauer des Containers exfiltriert werden kann, und entfernen Sie den genauen benannten Container sofort danach.

Führen Sie die gleiche fokussierte Suite nativ auf dem Host aus:

npm run test:plugin-setup-platform

Überprüfen Sie die erstellte Identität und Umgebung, bevor Sie dem Image vertrauen:

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

Bereinigen Sie jedes benannte Testprojekt, ohne nicht zusammenhängende Volumes oder Images zu löschen:

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/

Debugging

Häufige Befehle

# Logs anzeigen
docker compose logs -f app           # App-Logs verfolgen
docker compose logs --tail=50 db     # Letzte 50 Zeilen von db

# Befehle im laufenden Container ausführen
docker compose exec app sh           # Shell in App öffnen
docker compose exec db psql -U postgres  # Mit postgres verbinden

# Überprüfen
docker compose ps                     # Laufende Dienste anzeigen
docker compose top                    # Prozesse in jedem Container
docker stats                          # Ressourcennutzung

# Neu erstellen
docker compose up --build             # Images neu erstellen
docker compose build --no-cache app   # Vollständigen Neubau erzwingen

# Aufräumen
docker compose down                   # Container und Netzwerke anhalten und entfernen
docker compose down -v                # Auch Volumes entfernen (ZERSTÖRERISCH)
docker system prune                   # Ungenutzte Images/Container entfernen

Netzwerkprobleme debuggen

# DNS-Auflösung im Container prüfen
docker compose exec app nslookup db

# Konnektivität prüfen
docker compose exec app wget -qO- http://api:3000/health

# Netzwerk überprüfen
docker network ls
docker network inspect <project>_default

Anti-Patterns

Schlecht: 'latest'-Tag im Dockerfile

# ❌ Vermeiden
FROM node:latest

Schlecht: Datenbank-Passwörter hartcodieren

# ❌ Vermeiden
services:
  db:
    environment:
      POSTGRES_PASSWORD: mein-schlechtes-passwort

Schlecht: Container als Root ausführen

# ❌ Vermeiden
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3
CMD ["python3", "app.py"]

Schlecht: Alle Ports für Dienste freigeben (db, redis)

# ❌ Vermeiden, wenn von außen nicht benötigt
services:
  db:
    ports:
      - "5432:5432"   # Nur innerhalb des Docker-Netzwerks benötigt

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.

Verwandte Skills