compose-patterns-2025
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDocker Compose Patterns for Production (2025)
2025年Docker Compose生产环境模式
Overview
概述
This skill documents production-ready Docker Compose patterns and best practices for 2025, based on official Docker documentation and industry standards.
本文基于Docker官方文档及行业标准,记录了2025年适用于生产环境的Docker Compose模式与最佳实践。
File Format Changes (2025)
2025年文件格式变更
IMPORTANT: The field is now obsolete in Docker Compose v2.42+.
versionCorrect (2025):
yaml
services:
app:
image: myapp:latestIncorrect (deprecated):
yaml
version: '3.8' # DO NOT USE
services:
app:
image: myapp:latest重要提示: 在Docker Compose v2.42+版本中,字段已被弃用。
version正确写法(2025年):
yaml
services:
app:
image: myapp:latest错误写法(已废弃):
yaml
version: '3.8' # 请勿使用
services:
app:
image: myapp:latestMultiple Environment Strategy
多环境策略
Pattern: Base + Environment Overrides
模式:基础配置 + 环境覆盖
compose.yaml (base):
yaml
services:
app:
build:
context: ./app
dockerfile: Dockerfile
environment:
- NODE_ENV=production
restart: unless-stoppedcompose.override.yaml (development - auto-loaded):
yaml
services:
app:
build:
target: development
volumes:
- ./app/src:/app/src:cached
environment:
- NODE_ENV=development
- DEBUG=*
ports:
- "9229:9229" # Debuggercompose.prod.yaml (production - explicit):
yaml
services:
app:
build:
target: production
deploy:
replicas: 3
resources:
limits:
cpus: '1'
memory: 512M
restart_policy:
condition: on-failure
max_attempts: 3Usage:
bash
undefinedcompose.yaml(基础配置):
yaml
services:
app:
build:
context: ./app
dockerfile: Dockerfile
environment:
- NODE_ENV=production
restart: unless-stoppedcompose.override.yaml(开发环境 - 自动加载):
yaml
services:
app:
build:
target: development
volumes:
- ./app/src:/app/src:cached
environment:
- NODE_ENV=development
- DEBUG=*
ports:
- "9229:9229" # 调试端口compose.prod.yaml(生产环境 - 显式指定):
yaml
services:
app:
build:
target: production
deploy:
replicas: 3
resources:
limits:
cpus: '1'
memory: 512M
restart_policy:
condition: on-failure
max_attempts: 3使用方式:
bash
undefinedDevelopment (auto-loads compose.override.yaml)
开发环境(自动加载compose.override.yaml)
docker compose up
docker compose up
Production
生产环境
docker compose -f compose.yaml -f compose.prod.yaml up -d
docker compose -f compose.yaml -f compose.prod.yaml up -d
CI/CD
CI/CD环境
docker compose -f compose.yaml -f compose.ci.yaml up --abort-on-container-exit
undefineddocker compose -f compose.yaml -f compose.ci.yaml up --abort-on-container-exit
undefinedEnvironment Variable Management
环境变量管理
Pattern: .env Files per Environment
模式:按环境拆分.env文件
.env.template (committed to git):
bash
undefined.env.template(提交至Git):
bash
undefinedDatabase
数据库
DB_HOST=sqlserver
DB_PORT=1433
DB_NAME=myapp
DB_USER=sa
DB_HOST=sqlserver
DB_PORT=1433
DB_NAME=myapp
DB_USER=sa
DB_PASSWORD= (set in actual .env)
DB_PASSWORD= (在实际.env文件中设置)
Redis
Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD= (set in actual .env)
REDIS_PASSWORD= (在实际.env文件中设置)
Application
应用程序
NODE_ENV=production
LOG_LEVEL=info
**.env.dev:**
```bash
DB_PASSWORD=Dev!Pass123
REDIS_PASSWORD=redis-dev-123
NODE_ENV=development
LOG_LEVEL=debug.env.prod:
bash
DB_PASSWORD=${PROD_DB_PASSWORD} # From CI/CD
REDIS_PASSWORD=${PROD_REDIS_PASSWORD}
NODE_ENV=production
LOG_LEVEL=infoLoad specific environment:
bash
docker compose --env-file .env.dev upNODE_ENV=production
LOG_LEVEL=info
**.env.dev:**
```bash
DB_PASSWORD=Dev!Pass123
REDIS_PASSWORD=redis-dev-123
NODE_ENV=development
LOG_LEVEL=debug.env.prod:
bash
DB_PASSWORD=${PROD_DB_PASSWORD} # 来自CI/CD环境
REDIS_PASSWORD=${PROD_REDIS_PASSWORD}
NODE_ENV=production
LOG_LEVEL=info加载指定环境:
bash
docker compose --env-file .env.dev upSecurity Patterns
安全模式
Pattern: Run as Non-Root User
模式:以非根用户运行
yaml
services:
app:
image: node:20-alpine
user: "1000:1000" # UID:GID
read_only: true
tmpfs:
- /tmp
- /app/.cache
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE # Only if binding to ports < 1024
security_opt:
- no-new-privileges:trueCreate user in Dockerfile:
dockerfile
FROM node:20-alpineyaml
services:
app:
image: node:20-alpine
user: "1000:1000" # UID:GID
read_only: true
tmpfs:
- /tmp
- /app/.cache
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE # 仅当需要绑定1024以下端口时添加
security_opt:
- no-new-privileges:true在Dockerfile中创建用户:
dockerfile
FROM node:20-alpineCreate app user
创建应用用户
RUN addgroup -g 1000 appuser &&
adduser -D -u 1000 -G appuser appuser
adduser -D -u 1000 -G appuser appuser
RUN addgroup -g 1000 appuser &&
adduser -D -u 1000 -G appuser appuser
adduser -D -u 1000 -G appuser appuser
Set ownership
设置目录权限
WORKDIR /app
COPY --chown=appuser:appuser . .
USER appuser
undefinedWORKDIR /app
COPY --chown=appuser:appuser . .
USER appuser
undefinedPattern: Secrets Management
模式:密钥管理
Docker Swarm secrets (production):
yaml
services:
app:
secrets:
- db_password
- api_key
secrets:
db_password:
file: ./secrets/db_password.txt
api_key:
external: true # Managed by SwarmAccess secrets in application:
javascript
// Read from /run/secrets/
const fs = require('fs');
const dbPassword = fs.readFileSync('/run/secrets/db_password', 'utf8').trim();Development alternative (environment):
yaml
services:
app:
environment:
- DB_PASSWORD_FILE=/run/secrets/db_passwordDocker Swarm密钥(生产环境):
yaml
services:
app:
secrets:
- db_password
- api_key
secrets:
db_password:
file: ./secrets/db_password.txt
api_key:
external: true # 由Swarm管理在应用中访问密钥:
javascript
// 从/run/secrets/读取
const fs = require('fs');
const dbPassword = fs.readFileSync('/run/secrets/db_password', 'utf8').trim();开发环境替代方案(环境变量):
yaml
services:
app:
environment:
- DB_PASSWORD_FILE=/run/secrets/db_passwordHealth Check Patterns
健康检查模式
Pattern: Comprehensive Health Checks
模式:全面健康检查
HTTP endpoint:
yaml
services:
web:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 3s
retries: 3
start_period: 40sDatabase ping:
yaml
services:
postgres:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER"]
interval: 10s
timeout: 3s
retries: 3Custom script:
yaml
services:
app:
healthcheck:
test: ["CMD", "node", "/app/scripts/healthcheck.js"]
interval: 30s
timeout: 3s
retries: 3
start_period: 40shealthcheck.js:
javascript
const http = require('http');
const options = {
hostname: 'localhost',
port: 8080,
path: '/health',
timeout: 2000
};
const req = http.request(options, (res) => {
process.exit(res.statusCode === 200 ? 0 : 1);
});
req.on('error', () => process.exit(1));
req.on('timeout', () => {
req.destroy();
process.exit(1);
});
req.end();HTTP端点检查:
yaml
services:
web:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 3s
retries: 3
start_period: 40s数据库连通性检查:
yaml
services:
postgres:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER"]
interval: 10s
timeout: 3s
retries: 3自定义脚本检查:
yaml
services:
app:
healthcheck:
test: ["CMD", "node", "/app/scripts/healthcheck.js"]
interval: 30s
timeout: 3s
retries: 3
start_period: 40shealthcheck.js:
javascript
const http = require('http');
const options = {
hostname: 'localhost',
port: 8080,
path: '/health',
timeout: 2000
};
const req = http.request(options, (res) => {
process.exit(res.statusCode === 200 ? 0 : 1);
});
req.on('error', () => process.exit(1));
req.on('timeout', () => {
req.destroy();
process.exit(1);
});
req.end();Dependency Management
依赖管理
Pattern: Ordered Startup with Conditions
模式:带条件的有序启动
yaml
services:
web:
depends_on:
database:
condition: service_healthy
redis:
condition: service_started
migration:
condition: service_completed_successfully
database:
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
interval: 10s
redis:
# No health check needed, just wait for start
migration:
image: myapp:latest
command: npm run migrate
restart: "no" # Run once
depends_on:
database:
condition: service_healthyyaml
services:
web:
depends_on:
database:
condition: service_healthy
redis:
condition: service_started
migration:
condition: service_completed_successfully
database:
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
interval: 10s
redis:
# 无需健康检查,只需等待启动完成
migration:
image: myapp:latest
command: npm run migrate
restart: "no" # 仅运行一次
depends_on:
database:
condition: service_healthyNetwork Isolation Patterns
网络隔离模式
Pattern: Three-Tier Network Architecture
模式:三层网络架构
yaml
services:
nginx:
image: nginx:alpine
networks:
- frontend
ports:
- "80:80"
api:
build: ./api
networks:
- frontend
- backend
database:
image: postgres:16-alpine
networks:
- backend # No frontend access
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # No external accessyaml
services:
nginx:
image: nginx:alpine
networks:
- frontend
ports:
- "80:80"
api:
build: ./api
networks:
- frontend
- backend
database:
image: postgres:16-alpine
networks:
- backend # 禁止前端访问
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 禁止外部访问Pattern: Service-Specific Networks
模式:服务专属网络
yaml
services:
web-app:
networks:
- public
- app-network
api:
networks:
- app-network
- data-network
postgres:
networks:
- data-network
redis:
networks:
- data-network
networks:
public:
driver: bridge
app-network:
driver: bridge
internal: true
data-network:
driver: bridge
internal: trueyaml
services:
web-app:
networks:
- public
- app-network
api:
networks:
- app-network
- data-network
postgres:
networks:
- data-network
redis:
networks:
- data-network
networks:
public:
driver: bridge
app-network:
driver: bridge
internal: true
data-network:
driver: bridge
internal: trueVolume Patterns
卷管理模式
Pattern: Named Volumes for Persistence
模式:命名卷持久化
yaml
services:
database:
volumes:
- db-data:/var/lib/postgresql/data # Persistent data
- ./init:/docker-entrypoint-initdb.d:ro # Init scripts (read-only)
- db-logs:/var/log/postgresql # Logs
volumes:
db-data:
driver: local
driver_opts:
type: none
o: bind
device: /mnt/data/postgres # Host path
db-logs:
driver: localyaml
services:
database:
volumes:
- db-data:/var/lib/postgresql/data # 持久化数据
- ./init:/docker-entrypoint-initdb.d:ro # 初始化脚本(只读)
- db-logs:/var/log/postgresql # 日志存储
volumes:
db-data:
driver: local
driver_opts:
type: none
o: bind
device: /mnt/data/postgres # 宿主机路径
db-logs:
driver: localPattern: Development Bind Mounts
模式:开发环境绑定挂载
yaml
services:
app:
volumes:
- ./src:/app/src:cached # macOS optimization
- /app/node_modules # Don't overwrite installed modules
- app-cache:/app/.cache # Named volume for cacheVolume mount options:
- - Read-only
:ro - - Read-write (default)
:rw - - macOS performance optimization (host authoritative)
:cached - - macOS performance optimization (container authoritative)
:delegated - - SELinux single container
:z - - SELinux multi-container
:Z
yaml
services:
app:
volumes:
- ./src:/app/src:cached # macOS性能优化
- /app/node_modules # 不覆盖已安装的依赖
- app-cache:/app/.cache # 缓存使用命名卷卷挂载选项:
- - 只读
:ro - - 读写(默认)
:rw - - macOS性能优化(宿主机优先)
:cached - - macOS性能优化(容器优先)
:delegated - - SELinux单容器模式
:z - - SELinux多容器模式
:Z
Resource Management Patterns
资源管理模式
Pattern: CPU and Memory Limits
模式:CPU与内存限制
yaml
services:
app:
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256MCalculate total resources:
yaml
undefinedyaml
services:
app:
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M计算总资源需求:
yaml
undefined3 app replicas + database + redis
3个app副本 + 数据库 + Redis
services:
app:
deploy:
replicas: 3
resources:
limits:
cpus: '0.5' # 3 x 0.5 = 1.5 CPUs
memory: 512M # 3 x 512M = 1.5GB
database:
deploy:
resources:
limits:
cpus: '2' # 2 CPUs
memory: 4G # 4GB
redis:
deploy:
resources:
limits:
cpus: '0.5' # 0.5 CPUs
memory: 512M # 512MB
services:
app:
deploy:
replicas: 3
resources:
limits:
cpus: '0.5' # 3 × 0.5 = 1.5核CPU
memory: 512M # 3 × 512M = 1.5GB内存
database:
deploy:
resources:
limits:
cpus: '2' # 2核CPU
memory: 4G # 4GB内存
redis:
deploy:
resources:
limits:
cpus: '0.5' # 0.5核CPU
memory: 512M # 512MB内存
Total: 4 CPUs, 6GB RAM minimum
总计:至少需要4核CPU,6GB内存
undefinedundefinedLogging Patterns
日志模式
Pattern: Centralized Logging
模式:集中式日志
yaml
services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
compress: "true"
labels: "app,environment"Alternative: Log to stdout/stderr (12-factor):
yaml
services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"View logs:
bash
docker compose logs -f app
docker compose logs --since 30m app
docker compose logs --tail 100 appyaml
services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
compress: "true"
labels: "app,environment"替代方案:输出至stdout/stderr(12要素原则):
yaml
services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"查看日志:
bash
docker compose logs -f app
docker compose logs --since 30m app
docker compose logs --tail 100 appInit Container Pattern
初始化容器模式
Pattern: Database Migration
模式:数据库迁移
yaml
services:
migration:
image: myapp:latest
command: npm run migrate
depends_on:
database:
condition: service_healthy
restart: "no" # Run once
networks:
- backend
app:
image: myapp:latest
depends_on:
migration:
condition: service_completed_successfully
networks:
- backendyaml
services:
migration:
image: myapp:latest
command: npm run migrate
depends_on:
database:
condition: service_healthy
restart: "no" # 仅运行一次
networks:
- backend
app:
image: myapp:latest
depends_on:
migration:
condition: service_completed_successfully
networks:
- backendYAML Anchors and Aliases
YAML锚点与别名
Pattern: Reusable Configuration
模式:可复用配置
yaml
x-common-app-config: &common-app
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
services:
app1:
<<: *common-app
build: ./app1
ports:
- "8001:8080"
app2:
<<: *common-app
build: ./app2
ports:
- "8002:8080"
app3:
<<: *common-app
build: ./app3
ports:
- "8003:8080"yaml
x-common-app-config: &common-app
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
services:
app1:
<<: *common-app
build: ./app1
ports:
- "8001:8080"
app2:
<<: *common-app
build: ./app2
ports:
- "8002:8080"
app3:
<<: *common-app
build: ./app3
ports:
- "8003:8080"Pattern: Environment-Specific Overrides
模式:按环境覆盖配置
yaml
x-logging: &default-logging
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
x-resources: &default-resources
limits:
cpus: '1'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
services:
app:
logging: *default-logging
deploy:
resources: *default-resourcesyaml
x-logging: &default-logging
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
x-resources: &default-resources
limits:
cpus: '1'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
services:
app:
logging: *default-logging
deploy:
resources: *default-resourcesPort Binding Patterns
端口绑定模式
Pattern: Security-First Port Binding
模式:安全优先的端口绑定
yaml
services:
# Public services
web:
ports:
- "80:8080"
- "443:8443"
# Development only (localhost binding)
debug:
ports:
- "127.0.0.1:9229:9229" # Debugger only accessible from host
# Environment-based binding
app:
ports:
- "${DOCKER_WEB_PORT_FORWARD:-127.0.0.1:8000}:8000"Environment control:
bash
undefinedyaml
services:
# 公开服务
web:
ports:
- "80:8080"
- "443:8443"
# 仅开发环境使用(绑定localhost)
debug:
ports:
- "127.0.0.1:9229:9229" # 调试端口仅允许宿主机访问
# 基于环境的动态绑定
app:
ports:
- "${DOCKER_WEB_PORT_FORWARD:-127.0.0.1:8000}:8000"环境变量控制:
bash
undefinedDevelopment (.env.dev)
开发环境(.env.dev)
DOCKER_WEB_PORT_FORWARD=127.0.0.1:8000 # Localhost only
DOCKER_WEB_PORT_FORWARD=127.0.0.1:8000 # 仅允许本地访问
Production (.env.prod)
生产环境(.env.prod)
DOCKER_WEB_PORT_FORWARD=8000 # All interfaces
undefinedDOCKER_WEB_PORT_FORWARD=8000 # 允许所有接口访问
undefinedRestart Policy Patterns
重启策略模式
yaml
services:
# Always restart (production services)
app:
restart: always
# Restart unless manually stopped (most common)
database:
restart: unless-stopped
# Never restart (one-time tasks)
migration:
restart: "no"
# Restart on failure only (with Swarm)
worker:
deploy:
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120syaml
services:
# 始终重启(生产环境服务)
app:
restart: always
# 除非手动停止,否则重启(最常用)
database:
restart: unless-stopped
# 从不重启(一次性任务)
migration:
restart: "no"
# 仅在失败时重启(Swarm环境)
worker:
deploy:
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120sValidation and Testing
验证与测试
Pattern: Pre-Deployment Validation
模式:部署前验证
bash
#!/bin/bash
set -euo pipefail
echo "Validating Compose syntax..."
docker compose config > /dev/null
echo "Building images..."
docker compose build
echo "Running security scan..."
for service in $(docker compose config --services); do
image=$(docker compose config | yq ".services.$service.image")
if [ -n "$image" ]; then
docker scout cves "$image" || true
fi
done
echo "Starting services..."
docker compose up -d
echo "Checking health..."
sleep 10
docker compose ps
echo "Running smoke tests..."
curl -f http://localhost:8080/health || exit 1
echo "✓ All checks passed"bash
#!/bin/bash
set -euo pipefail
echo "验证Compose语法..."
docker compose config > /dev/null
echo "构建镜像..."
docker compose build
echo "运行安全扫描..."
for service in $(docker compose config --services); do
image=$(docker compose config | yq ".services.$service.image")
if [ -n "$image" ]; then
docker scout cves "$image" || true
fi
done
echo "启动服务..."
docker compose up -d
echo "检查健康状态..."
sleep 10
docker compose ps
echo "运行冒烟测试..."
curl -f http://localhost:8080/health || exit 1
echo "✓ 所有检查通过"Complete Production Example
完整生产环境示例
yaml
undefinedyaml
undefinedModern Compose format (no version field for v2.40+)
新版Compose格式(v2.40+无需version字段)
x-common-service: &common-service
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
security_opt:
- no-new-privileges:true
services:
nginx:
<<: *common-service
image: nginxinc/nginx-unprivileged:alpine
ports:
- "80:8080"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
networks:
- frontend
depends_on:
api:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"]
interval: 30s
api:
<<: *common-service
build:
context: ./api
dockerfile: Dockerfile
target: production
user: "1000:1000"
read_only: true
tmpfs:
- /tmp
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
networks:
- frontend
- backend
depends_on:
migration:
condition: service_completed_successfully
redis:
condition: service_started
env_file:
- .env
healthcheck:
test: ["CMD", "node", "healthcheck.js"]
interval: 30s
start_period: 40s
deploy:
resources:
limits:
cpus: '1'
memory: 512M
migration:
image: myapp:latest
command: npm run migrate
restart: "no"
networks:
- backend
depends_on:
postgres:
condition: service_healthy
postgres:
<<: *common-service
image: postgres:16-alpine
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/postgres_password
secrets:
- postgres_password
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- backend
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
interval: 10s
deploy:
resources:
limits:
cpus: '1'
memory: 2G
redis:
<<: *common-service
image: redis:7.4-alpine
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis-data:/data
networks:
- backend
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true
volumes:
postgres-data:
driver: local
redis-data:
driver: local
secrets:
postgres_password:
file: ./secrets/postgres_password.txt
undefinedx-common-service: &common-service
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
security_opt:
- no-new-privileges:true
services:
nginx:
<<: *common-service
image: nginxinc/nginx-unprivileged:alpine
ports:
- "80:8080"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
networks:
- frontend
depends_on:
api:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"]
interval: 30s
api:
<<: *common-service
build:
context: ./api
dockerfile: Dockerfile
target: production
user: "1000:1000"
read_only: true
tmpfs:
- /tmp
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
networks:
- frontend
- backend
depends_on:
migration:
condition: service_completed_successfully
redis:
condition: service_started
env_file:
- .env
healthcheck:
test: ["CMD", "node", "healthcheck.js"]
interval: 30s
start_period: 40s
deploy:
resources:
limits:
cpus: '1'
memory: 512M
migration:
image: myapp:latest
command: npm run migrate
restart: "no"
networks:
- backend
depends_on:
postgres:
condition: service_healthy
postgres:
<<: *common-service
image: postgres:16-alpine
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/postgres_password
secrets:
- postgres_password
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- backend
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
interval: 10s
deploy:
resources:
limits:
cpus: '1'
memory: 2G
redis:
<<: *common-service
image: redis:7.4-alpine
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis-data:/data
networks:
- backend
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true
volumes:
postgres-data:
driver: local
redis-data:
driver: local
secrets:
postgres_password:
file: ./secrets/postgres_password.txt
undefinedCommon Mistakes to Avoid
常见错误规避
- Using field - Obsolete in 2025
version - No health checks - Leads to race conditions
- Running as root - Security risk
- No resource limits - Can exhaust host resources
- Hardcoded secrets - Use secrets or environment variables
- No logging limits - Disk space issues
- Bind mounts in production - Use named volumes
- Missing restart policies - Services don't recover
- No network isolation - All services can talk to each other
- Not using .dockerignore - Larger build contexts
- 使用字段 - 2025年已废弃
version - 未配置健康检查 - 会导致启动竞争问题
- 以根用户运行 - 存在安全风险
- 未设置资源限制 - 可能耗尽宿主机资源
- 硬编码密钥 - 应使用密钥管理或环境变量
- 未设置日志限制 - 可能导致磁盘空间不足
- 生产环境使用绑定挂载 - 应使用命名卷
- 缺失重启策略 - 服务故障后无法自动恢复
- 未做网络隔离 - 所有服务可互相访问
- 未使用.dockerignore - 构建上下文过大
Troubleshooting Commands
故障排查命令
bash
undefinedbash
undefinedValidate syntax
验证语法
docker compose config
docker compose config
View merged configuration
查看合并后的配置
docker compose config --services
docker compose config --services
Check which file is being used
检查正在使用的配置文件
docker compose config --files
docker compose config --files
View environment interpolation
查看未插值的环境变量
docker compose config --no-interpolate
docker compose config --no-interpolate
Check service dependencies
检查服务依赖关系
docker compose config | yq '.services.*.depends_on'
docker compose config | yq '.services.*.depends_on'
View resource usage
查看资源使用情况
docker stats $(docker compose ps -q)
docker stats $(docker compose ps -q)
Debug startup issues
调试启动问题
docker compose up --no-deps service-name
docker compose up --no-deps service-name
Force recreate
强制重新创建容器
docker compose up --force-recreate service-name
undefineddocker compose up --force-recreate service-name
undefined