docker-patterns
Skill0 starsChanged 9 days agoMITView on GitHub
Docker and Docker Compose patterns for local development, hardened CLI installer harnesses, container security, networking, volumes, and multi-service orchestration. Use when creating or reviewing Dockerfiles and Compose services, testing installers across Linux distributions, or planning accurate native macOS and Windows validation.
- Reads credentials
- Installs packages
43 other projects use a version of this, 35 of them edited.
Adopted by
Most recently taken up by
- Rojios/everything-claude-codeedited, first seen Nov 8, 2026
- lhbsaa/apex-unifiededited, first seen Nov 8, 2026
- Lukk17/agent-standardstheir own version, first seen Nov 7, 2026
- pankaj-mahaur/Agent-Daemonedited, first seen Nov 6, 2026
- ku5ic/claude-kittheir own version, first seen Nov 4, 2026
- shubh3794/claude-code-portableedited, first seen Nov 1, 2026
Used with
Projects with it also use content-hash-cache-pattern, configure-ecc and 9 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
royaluniondesign-sysSkillcontent-hash-cache-pattern
Cache expensive file processing results using SHA-256 content hashes — path-independent, auto-invalidating, with service layer separation.
Also in 14 projects that use this
royaluniondesign-sysSkillconfigure-ecc
Interactive installer for Everything Claude Code — guides users through selecting and installing skills and rules to user-level or project-level directories, verifies paths, and optionally optimizes installed files.
Also in 9 projects that use this
junimnjwSkillralphinho-rfc-pipeline
RFC-driven multi-agent DAG execution pattern with quality gates, merge queues, and work unit orchestration.
Also in 9 projects that use this
Yog-SothoSkillpytorch-patterns
PyTorch deep learning patterns and best practices for building robust, efficient, and reproducible training pipelines, model architectures, and data loading. Always activate when the user is writing PyTorch models or training scripts, reviewing deep learning code, debugging training loops or data pipelines, optimizing GPU memory or training speed, setting up reproducible experiments, implementing transfer learning or fine-tuning, or asks anything about nn.Module, DataLoader, autograd, AMP, or torch.compile.
Also in 11 projects that use this
loulanyueSkillnuxt4-patterns
Nuxt 4 app patterns for hydration safety, performance, route rules, lazy loading, and SSR-safe data fetching with useFetch and useAsyncData.
Also in 7 projects that use this
junimnjwSkillcarrier-relationship-management
Codified expertise for managing carrier portfolios, negotiating freight rates, tracking carrier performance, allocating freight, and maintaining strategic carrier relationships. Informed by transportation managers with 15+ years experience. Includes scorecarding frameworks, RFP processes, market intelligence, and compliance vetting. Use when managing carriers, negotiating rates, evaluating carrier performance, or building freight strategies.
Also in 7 projects that use this
- +3 more from royaluniondesign-sys
- +1 more from junimnjw
Other versions43 projects use a version of this.
Word for word · 1
- Ronnasayd/aipp★ 1100% same
Edited · 35
- loulanyue/awesome-claude-notes★ 27294% same
- tranhieutt/software_development_department★ 7189% same
- Fmarzochi/EGC★ 6194% same
- skateddu/claude-code-python-setup★ 2898% same
- woxiangyangzhimao/skills★ 1491% same
- gongyijie85/dsh-ecc★ 899% same
- VoVuongThanhDat/agentflow★ 894% same
- Yog-Sotho/claude-skills★ 430% same
- raniellimontagna/agent-toolkit★ 379% same
- ronmkr/PromptBook★ 294% same
25 more not listed
Wrote their own version · 7
- langchain-ai/skills-benchmarks★ 116same name
- sabahattink/antigravity-fullstack-hq★ 30same name
- pekral/cursor-rules★ 10same name
- edjchapman/claude-code-config★ 8same name
- ku5ic/claude-kit★ 2same name
- Lukk17/agent-standards★ 1same name
- thanvish21/hcc-bundle★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository39 other files it gives its agents.
- agent-architecture-auditSkill
- agent-evalSkill
- agent-harness-constructionSkill
- agent-introspection-debuggingSkill
- agent-security-hardeningSkill
- agent-self-evaluationSkill
- iterative-retrievalSkill
- prompt-optimizerSkill
- backend-patternsSkill
- database-migrationsSkill
- error-handlingSkill
- fastapi-patternsSkill
- postgres-patternsSkill
- redis-patternsSkill
- accessibilitySkill
- design-systemSkill
- frontend-patternsSkill
- react-performanceSkill
- golang-testingSkill
- kubernetes-patternsSkill
- python-testingSkill
- react-testingSkill
- rust-testingSkill
- content-engineSkill
- market-researchSkill
- seoSkill
- api-designSkill
- brownfield-retrospectiveSkill
- codebase-onboardingSkill
- coding-standardsSkill
- context-budgetSkill
- continuous-learningSkill
- conventional-commit-reviewSkill
- orch-pipelineSkill
- plan-orchestrateSkill
- security-reviewSkill
- tdd-workflowSkill
- unified-memorySkill
- verification-loopSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
18 rules. 0 are common, 9 are distinctive, and 9 are very specific to this project.
0
Common
Most of the 11 edited versions we read keep these.
9
Distinctive
This author's own choices. Worth a look.
9
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 277
Use containers to test installer behavior against disposable project copies without allowing the test to mutate the source checkout.
- Distinctive: line 281
Run real containers for Linux distributions such as Debian and Ubuntu.
- Very specific: line 284
Keep a native Ubuntu/macOS/Windows CI matrix for host-specific paths, command shims, quoting, and filesystem behavior.
- Distinctive: line 286
Do not claim that a Linux container validates macOS or Windows behavior.
- Distinctive: line 291
Run as a non-root numeric UID/GID when distro account names differ.
- Very specific: line 296
Keep npm and npx's executable cache at NPM_CONFIG_CACHE=/tmp/npm-cache on the executable /tmp mount.
- Very specific: line 301
Keep the default real-CLI services on network_mode: none.
- Distinctive: line 304
Create only the writable temporary paths the tool needs.
- Distinctive: line 305
Do not pass host credentials into the container by default.
- Very specific: line 306
Default to a dry run and whitelist only the explicit dry-run, install, plugin, and shell modes.
- Very specific: line 308
Use argument arrays or spawnSync(..., { shell: false }) for cross-platform runners.
- Very specific: line 312
Use docker/plugin-setup/compose.yaml as the reference implementation.
- Distinctive: line 331
Run the safe default flow in each image:
- Very specific: line 349
Before that command runs, the container creates a locally packed npm artifact from the read-only checkout with npm pack --ignore-scripts.
- Very specific: line 365
Start a detached container without --rm so leaving a terminal does not remove the session:
- Very specific: line 415
Prefer authenticating inside that disposable session.
- Distinctive: line 449
Only one container can hold host port 1455 at a time because the OAuth redirect targets a fixed port.
- Distinctive: line 458
Run the same focused suite natively on the host:
“Common” is measured: kept by at least 6 in 10 of the 11 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Docker Patterns
Docker and Docker Compose best practices for containerized development.
Docker Compose for Local Development
Standard Web App Stack
# docker-compose.yml
services:
app:
build:
context: .
target: dev # Use dev stage of multi-stage Dockerfile
ports:
- "3000:3000"
volumes:
- .:/app # Bind mount for hot reload
- /app/node_modules # Anonymous volume -- preserves container deps
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: # Local email testing
image: axllent/mailpit
ports:
- "8025:8025" # Web UI
- "1025:1025" # SMTP
volumes:
pgdata:
redisdata:Development vs Production Dockerfile
# 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 (minimal 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 Files
# docker-compose.override.yml (auto-loaded, dev-only settings)
services:
app:
environment:
- DEBUG=app:*
- LOG_LEVEL=debug
ports:
- "9229:9229" # Node.js debugger
# docker-compose.prod.yml (explicit for production)
services:
app:
build:
target: production
restart: always
deploy:
resources:
limits:
cpus: "1.0"
memory: 512M# Development (auto-loads override)
docker compose up
# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -dNetworking
Service Discovery
Services in the same Compose network resolve by service name:
# From "app" container:
postgres://postgres:postgres@db:5432/app_dev # "db" resolves to the db container
redis://redis:6379/0 # "redis" resolves to the redis containerCustom Networks
services:
frontend:
networks:
- frontend-net
api:
networks:
- frontend-net
- backend-net
db:
networks:
- backend-net # Only reachable from api, not frontend
networks:
frontend-net:
backend-net:Exposing Only What's Needed
services:
db:
ports:
- "127.0.0.1:5432:5432" # Only accessible from host, not network
# Omit ports entirely in production -- accessible only within Docker networkVolume Strategies
volumes:
# Named volume: persists across container restarts, managed by Docker
pgdata:
# Bind mount: maps host directory into container (for development)
# - ./src:/app/src
# Anonymous volume: preserves container-generated content from bind mount override
# - /app/node_modulesCommon Patterns
services:
app:
volumes:
- .:/app # Source code (bind mount for hot reload)
- /app/node_modules # Protect container's node_modules from host
- /app/.next # Protect build cache
db:
volumes:
- pgdata:/var/lib/postgresql/data # Persistent data
- ./scripts/init.sql:/docker-entrypoint-initdb.d/init.sql # Init scriptsContainer Security
Dockerfile Hardening
# 1. Use specific tags (never :latest)
FROM node:22.12-alpine3.20
# 2. Run as non-root
RUN addgroup -g 1001 -S app && adduser -S app -u 1001
USER app
# 3. Drop capabilities (in compose)
# 4. Read-only root filesystem where possible
# 5. No secrets in image layersCompose Security
services:
app:
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
- /app/.cache
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE # Only if binding to ports < 1024Secret Management
# GOOD: Use environment variables (injected at runtime)
services:
app:
env_file:
- .env # Never commit .env to git
environment:
- API_KEY # Inherits from host environment
# GOOD: Docker secrets (Swarm mode)
secrets:
db_password:
file: ./secrets/db_password.txt
services:
db:
secrets:
- db_password
# BAD: Hardcoded in image
# ENV API_KEY=sk-proj-xxxxx # NEVER DO THISHardened CLI Installer Harnesses
Use containers to test installer behavior against disposable project copies without allowing the test to mutate the source checkout.
Respect the Platform Boundary
- Run real containers for Linux distributions such as Debian and Ubuntu.
- macOS cannot run as a Docker container because Docker shares a Linux kernel. Run the same shell-free test entry point natively on macOS.
- Windows containers require a Windows Docker engine. Run platform-independent logic on a native Windows CI runner and reserve Windows containers for a Windows host.
- Keep a native Ubuntu/macOS/Windows CI matrix for host-specific paths, command shims, quoting, and filesystem behavior.
Do not claim that a Linux container validates macOS or Windows behavior.
Enforce the Isolation Contract
- Pin base images by immutable digest and pin installed CLI versions.
- Run as a non-root numeric UID/GID when distro account names differ.
- Mount the repository and source project read-only.
- Copy the source project into a writable
tmpfsworkspace before any mutation. - Mount
/workspacewithnoexec, UID/GID 1000, andmode=0700so only the container user can inspect project data. - Keep npm and npx's executable cache at
NPM_CONFIG_CACHE=/tmp/npm-cacheon the executable/tmpmount. Its default size is 2 GiB and can be adjusted withECC_TMPFS_SIZE;ECC_WORKSPACE_SIZEseparately controls the private workspace mount. - Set
read_only: true,no-new-privileges:true,cap_drop: [ALL], and a finitepids_limit. - Keep the default real-CLI services on
network_mode: none. Add network access only through a visibly named opt-in service for an authenticated provider session; never make it an accidental environment-driven default. - Create only the writable temporary paths the tool needs.
- Do not pass host credentials into the container by default.
- Default to a dry run and whitelist only the explicit
dry-run,install,plugin, andshellmodes. - Use argument arrays or
spawnSync(..., { shell: false })for cross-platform runners. Never interpolate project paths into a shell command.
Exercise the ECC Plugin Setup Harness
Use docker/plugin-setup/compose.yaml as the reference implementation. It provides:
fixture-testsfor the focused install manifest, target, and executor suite.real-clifor the pinned Debian-based generic Linux image.real-cli-ubuntufor the pinned Ubuntu image.
Validate the Compose model before building:
docker compose -f docker/plugin-setup/compose.yaml config --quietBuild both real Linux images:
docker compose -f docker/plugin-setup/compose.yaml \
build real-cli real-cli-ubuntuRun the safe default flow in each 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-runThe dry run executes the current public command contract:
ecc install --profile core --target claude-project --dry-run --jsonBefore that command runs, the container creates a locally packed npm artifact
from the read-only checkout with npm pack --ignore-scripts. It extracts the
self-created tarball under /tmp, validates the ecc-universal package name,
required install manifests, and the confined package.json bin.ecc mapping,
then invokes the extracted ecc executable. The runtime stays on
network_mode: none, does not execute package lifecycle scripts, and does not
rely on host node_modules; its exact pinned production dependencies are
already present in the image.
The harness rejects an empty plan, a non-claude-project target, any operation
outside /workspace/project/.claude, or any dry run that creates the target
directory. install performs the isolated apply twice, checks its managed
install state, lists the installed target, and runs doctor.
Start, Open, Reconnect, and Clean Up a Named Session
Start a detached container without --rm so leaving a terminal does not remove
the session:
docker compose -p ecc-plugin-session \
-f docker/plugin-setup/compose.yaml \
run --detach --name ecc-plugin-shell real-cli shellThe container copies the read-only fixture to the stable private directory
/workspace/project. Confirm it is running, then emit the Docker side of the
terminal-opener v1 data contract:
docker inspect --format '{{.State.Running}}' ecc-plugin-shell
node docker/plugin-setup/interactive-plan.js \
--container ecc-plugin-shell \
--workdir /workspace/project \
--json \
-- bashThe JSON result has exactly an executable and argv boundary (plus
contractVersion: 1): the executable is docker, and argv begins with
exec, -it, and -w. Pass that data to the separate terminal-opener skill
when it is installed. This Docker harness deliberately does not import a
terminal adapter, interpolate a shell command, or manage a host GUI process.
Until then, open the same PTY in the current host terminal directly:
docker exec -it -w /workspace/project ecc-plugin-shell bashExit the shell without stopping the detached container. Reconnect with the
same docker exec -it command. When finished, remove the exact named container
and its Compose project resources:
docker rm --force ecc-plugin-shell
docker compose -p ecc-plugin-session \
-f docker/plugin-setup/compose.yaml \
down --remove-orphansHost credentials are absent by default and credential directories are never
mounted. The default service also has no network access. When an authenticated
provider session genuinely needs a network, build real-cli first and then opt
in visibly with docker compose -f docker/plugin-setup/compose.yaml
--profile networked run --service-ports real-cli-networked shell. The
--service-ports flag publishes the service's loopback callback mapping.
Prefer authenticating inside that disposable session. If a CI run must
inherit a host environment credential, make that opt-in at invocation with an
explicit Compose --env NAME flag, understand that the value is inspectable
and can be exfiltrated for the container lifetime, and remove the exact named
container immediately after.
Authenticate Codex Inside the Networked Session
codex login binds its OAuth callback server to 127.0.0.1:1455 inside the
container. A Docker port publish forwards to the container interface, not
loopback, so the host browser's redirect to http://localhost:1455 is refused
without a bridge. The real-cli-networked service publishes host
127.0.0.1:1455 to container port 1456; bridge that port to loopback before
logging in:
(
set -e
npm install --global @openai/codex@0.162.0 # the harness image does not ship codex
node /ecc/docker/plugin-setup/codex-auth-relay.js &
relay_pid=$!
trap 'kill "$relay_pid" 2>/dev/null || true; wait "$relay_pid" 2>/dev/null || true' EXIT
codex login
)The networked service sets NPM_CONFIG_PREFIX=/tmp/ecc-npm and adds its bin
directory to PATH. This keeps the pinned installation writable for UID 1000
on the executable /tmp mount while the root filesystem remains read-only.
Complete the sign-in in the host browser. Each attempt mints a fresh
state/code, so always follow the newest printed link. The token stays in
the disposable container's ~/.codex/auth.json; removing the named container
deletes that credential copy. The login block stops the relay on success or failure.
Only one container can hold host port 1455 at a time
because the OAuth redirect targets a fixed port.
The host publish is restricted to loopback. Inside the container, the relay listens on all interfaces so Docker can forward to it; other containers on the same bridge network can reach it while it runs. Use a dedicated network without untrusted peers for this login, and remove the exact named container after use. Idle callback connections close after 30 seconds.
Run the same focused suite natively on the host:
npm run test:plugin-setup-platformInspect the produced identity and environment before trusting the image:
docker image inspect ecc-plugin-setup:debian ecc-plugin-setup:ubuntuClean each named test project without deleting unrelated volumes or images:
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
Common Commands
# View logs
docker compose logs -f app # Follow app logs
docker compose logs --tail=50 db # Last 50 lines from db
# Execute commands in running container
docker compose exec app sh # Shell into app
docker compose exec db psql -U postgres # Connect to postgres
# Inspect
docker compose ps # Running services
docker compose top # Processes in each container
docker stats # Resource usage
# Rebuild
docker compose up --build # Rebuild images
docker compose build --no-cache app # Force full rebuild
# Clean up
docker compose down # Stop and remove containers
docker compose down -v # Also remove volumes (DESTRUCTIVE)
docker system prune # Remove unused images/containersDebugging Network Issues
# Check DNS resolution inside container
docker compose exec app nslookup db
# Check connectivity
docker compose exec app wget -qO- http://api:3000/health
# Inspect network
docker network ls
docker network inspect <project>_defaultAnti-Patterns
# BAD: Using docker compose in production without orchestration
# Use Kubernetes, ECS, or Docker Swarm for production multi-container workloads
# BAD: Storing data in containers without volumes
# Containers are ephemeral -- all data lost on restart without volumes
# BAD: Running as root
# Always create and use a non-root user
# BAD: Using :latest tag
# Pin to specific versions for reproducible builds
# BAD: One giant container with all services
# Separate concerns: one process per container
# BAD: Putting secrets in docker-compose.yml
# Use .env files (gitignored) or Docker secretsDoes it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

