docker-patterns
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDocker Patterns
Docker 模式
Docker and Docker Compose best practices for containerized development.
面向容器化开发的Docker和Docker Compose最佳实践。
When to Activate
适用场景
- Setting up Docker Compose for local development
- Designing multi-container architectures
- Troubleshooting container networking or volume issues
- Reviewing Dockerfiles for security and size
- Migrating from local dev to containerized workflow
- 为本地开发搭建Docker Compose环境
- 设计多容器架构
- 排查容器网络或卷相关问题
- 审查Dockerfile的安全性与镜像大小
- 从本地开发迁移至容器化工作流
Docker Compose for Local Development
用于本地开发的Docker Compose
Standard Web App Stack
标准Web应用栈
yaml
undefinedyaml
undefineddocker-compose.yml
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:
undefinedservices:
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:
undefinedDevelopment vs Production Dockerfile
开发与生产环境Dockerfile对比
dockerfile
undefineddockerfile
undefinedStage: dependencies
Stage: dependencies
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
Stage: dev (hot reload, debug tools)
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"]
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
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
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)
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"]
undefinedFROM 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"]
undefinedOverride Files
覆盖文件
yaml
undefinedyaml
undefineddocker-compose.override.yml (auto-loaded, dev-only settings)
docker-compose.override.yml (auto-loaded, dev-only settings)
services:
app:
environment:
- DEBUG=app:*
- LOG_LEVEL=debug
ports:
- "9229:9229" # Node.js debugger
services:
app:
environment:
- DEBUG=app:*
- LOG_LEVEL=debug
ports:
- "9229:9229" # Node.js debugger
docker-compose.prod.yml (explicit for production)
docker-compose.prod.yml (explicit for production)
services:
app:
build:
target: production
restart: always
deploy:
resources:
limits:
cpus: "1.0"
memory: 512M
```bashservices:
app:
build:
target: production
restart: always
deploy:
resources:
limits:
cpus: "1.0"
memory: 512M
```bashDevelopment (auto-loads override)
Development (auto-loads override)
docker compose up
docker compose up
Production
Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
undefineddocker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
undefinedNetworking
网络配置
Service Discovery
服务发现
Services in the same Compose network resolve by service name:
undefined同一Compose网络中的服务可通过服务名称解析:
undefinedFrom "app" container:
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 container
undefinedpostgres://postgres:postgres@db:5432/app_dev # "db" resolves to the db container
redis://redis:6379/0 # "redis" resolves to the redis container
undefinedCustom Networks
自定义网络
yaml
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:yaml
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
仅暴露必要端口
yaml
services:
db:
ports:
- "127.0.0.1:5432:5432" # Only accessible from host, not network
# Omit ports entirely in production -- accessible only within Docker networkyaml
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
卷策略
yaml
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_modulesyaml
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
常见模式
yaml
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 scriptsyaml
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
Dockerfile 加固
dockerfile
undefineddockerfile
undefined1. Use specific tags (never :latest)
1. Use specific tags (never :latest)
FROM node:22.12-alpine3.20
FROM node:22.12-alpine3.20
2. Run as non-root
2. Run as non-root
RUN addgroup -g 1001 -S app && adduser -S app -u 1001
USER app
RUN addgroup -g 1001 -S app && adduser -S app -u 1001
USER app
3. Drop capabilities (in compose)
3. Drop capabilities (in compose)
4. Read-only root filesystem where possible
4. Read-only root filesystem where possible
5. No secrets in image layers
5. No secrets in image layers
undefinedundefinedCompose Security
Compose 安全配置
yaml
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 < 1024yaml
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
密钥管理
yaml
undefinedyaml
undefinedGOOD: Use environment variables (injected at runtime)
GOOD: Use environment variables (injected at runtime)
services:
app:
env_file:
- .env # Never commit .env to git
environment:
- API_KEY # Inherits from host environment
services:
app:
env_file:
- .env # Never commit .env to git
environment:
- API_KEY # Inherits from host environment
GOOD: Docker secrets (Swarm mode)
GOOD: Docker secrets (Swarm mode)
secrets:
db_password:
file: ./secrets/db_password.txt
services:
db:
secrets:
- db_password
secrets:
db_password:
file: ./secrets/db_password.txt
services:
db:
secrets:
- db_password
BAD: Hardcoded in image
BAD: Hardcoded in image
ENV API_KEY=sk-proj-xxxxx # NEVER DO THIS
ENV API_KEY=sk-proj-xxxxx # NEVER DO THIS
undefinedundefined.dockerignore
.dockerignore 文件
node_modules
.git
.env
.env.*
dist
coverage
*.log
.next
.cache
docker-compose*.yml
Dockerfile*
README.md
tests/node_modules
.git
.env
.env.*
dist
coverage
*.log
.next
.cache
docker-compose*.yml
Dockerfile*
README.md
tests/Debugging
调试方法
Common Commands
常用命令
bash
undefinedbash
undefinedView logs
View logs
docker compose logs -f app # Follow app logs
docker compose logs --tail=50 db # Last 50 lines from db
docker compose logs -f app # Follow app logs
docker compose logs --tail=50 db # Last 50 lines from db
Execute commands in running container
Execute commands in running container
docker compose exec app sh # Shell into app
docker compose exec db psql -U postgres # Connect to postgres
docker compose exec app sh # Shell into app
docker compose exec db psql -U postgres # Connect to postgres
Inspect
Inspect
docker compose ps # Running services
docker compose top # Processes in each container
docker stats # Resource usage
docker compose ps # Running services
docker compose top # Processes in each container
docker stats # Resource usage
Rebuild
Rebuild
docker compose up --build # Rebuild images
docker compose build --no-cache app # Force full rebuild
docker compose up --build # Rebuild images
docker compose build --no-cache app # Force full rebuild
Clean up
Clean up
docker compose down # Stop and remove containers
docker compose down -v # Also remove volumes (DESTRUCTIVE)
docker system prune # Remove unused images/containers
undefineddocker compose down # Stop and remove containers
docker compose down -v # Also remove volumes (DESTRUCTIVE)
docker system prune # Remove unused images/containers
undefinedDebugging Network Issues
排查网络问题
bash
undefinedbash
undefinedCheck DNS resolution inside container
Check DNS resolution inside container
docker compose exec app nslookup db
docker compose exec app nslookup db
Check connectivity
Check connectivity
docker compose exec app wget -qO- http://api:3000/health
docker compose exec app wget -qO- http://api:3000/health
Inspect network
Inspect network
docker network ls
docker network inspect <project>_default
undefineddocker network ls
docker network inspect <project>_default
undefinedAnti-Patterns
反模式
undefinedundefinedBAD: Using docker compose in production without orchestration
BAD: Using docker compose in production without orchestration
Use Kubernetes, ECS, or Docker Swarm for production multi-container workloads
Use Kubernetes, ECS, or Docker Swarm for production multi-container workloads
BAD: Storing data in containers without volumes
BAD: Storing data in containers without volumes
Containers are ephemeral -- all data lost on restart without volumes
Containers are ephemeral -- all data lost on restart without volumes
BAD: Running as root
BAD: Running as root
Always create and use a non-root user
Always create and use a non-root user
BAD: Using :latest tag
BAD: Using :latest tag
Pin to specific versions for reproducible builds
Pin to specific versions for reproducible builds
BAD: One giant container with all services
BAD: One giant container with all services
Separate concerns: one process per container
Separate concerns: one process per container
BAD: Putting secrets in docker-compose.yml
BAD: Putting secrets in docker-compose.yml
Use .env files (gitignored) or Docker secrets
Use .env files (gitignored) or Docker secrets
undefinedundefined