Docker Compose生产环境部署完全指南:多容器应用、健康检查与零停机更新
Docker Compose将多容器应用的定义、配置和启动整合到一个YAML文件中,是小型团队和个人开发者最常用的容器编排方案。本文聚焦生产环境实践,涵盖健康检查、密钥管理、日志限制与零停机更新等关键配置。
一、生产级Compose文件结构
<code">version: '3.8'
# 定义网络(服务间通信走内部网络,不暴露到宿主机)
networks:
backend:
driver: bridge
internal: false # 需要访问外网(如下载依赖)
database:
driver: bridge
internal: true # 数据库网络不需要访问外网
# 持久化存储卷
volumes:
mysql_data:
driver: local
redis_data:
driver: local
app_uploads:
driver: local
services:
# ============ 应用服务 ============
app:
image: your-registry/your-app:${APP_VERSION:-latest}
restart: unless-stopped
networks:
- backend
- database
environment:
- NODE_ENV=production
- DB_HOST=mysql
- REDIS_HOST=redis
env_file:
- .env.production # 敏感配置从文件读取,不硬编码
volumes:
- app_uploads:/app/uploads
depends_on:
mysql:
condition: service_healthy # 等待MySQL健康才启动
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s # 启动后等待40秒再开始健康检查
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
memory: 256M
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5"
# ============ MySQL数据库 ============
mysql:
image: mysql:8.0
restart: unless-stopped
networks:
- database
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root_password
MYSQL_DATABASE: appdb
MYSQL_USER: appuser
MYSQL_PASSWORD_FILE: /run/secrets/mysql_password
secrets:
- mysql_root_password
- mysql_password
volumes:
- mysql_data:/var/lib/mysql
- ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
command: >
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
--innodb-buffer-pool-size=256M
--slow-query-log=1
--slow-query-log-file=/var/lib/mysql/slow.log
--long-query-time=2
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root",
"--password=$$(cat /run/secrets/mysql_root_password)"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
logging:
driver: "json-file"
options:
max-size: "20m"
max-file: "3"
# ============ Redis缓存 ============
redis:
image: redis:7-alpine
restart: unless-stopped
networks:
- database
command: >
redis-server
--requirepass $${REDIS_PASSWORD}
--maxmemory 256mb
--maxmemory-policy allkeys-lru
--appendonly yes
--save 900 1
environment:
- REDIS_PASSWORD_FILE=/run/secrets/redis_password
secrets:
- redis_password
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "--no-auth-warning", "-a",
"$$(cat /run/secrets/redis_password)", "ping"]
interval: 15s
timeout: 5s
retries: 3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ============ Nginx反向代理 ============
nginx:
image: nginx:alpine
restart: unless-stopped
networks:
- backend
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- /etc/letsencrypt:/etc/letsencrypt:ro
- app_uploads:/var/www/uploads:ro
depends_on:
app:
condition: service_healthy
healthcheck:
test: ["CMD", "nginx", "-t"]
interval: 60s
timeout: 10s
retries: 3
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "10"
# Docker Secrets(比环境变量更安全)
secrets:
mysql_root_password:
file: ./secrets/mysql_root_password.txt
mysql_password:
file: ./secrets/mysql_password.txt
redis_password:
file: ./secrets/redis_password.txt二、密钥安全管理
<code"># 创建密钥目录(加入.gitignore) mkdir -p secrets echo "密码至少32位随机字符" > secrets/mysql_root_password.txt echo "数据库用户密码" > secrets/mysql_password.txt echo "Redis密码" > secrets/redis_password.txt # 设置严格文件权限 chmod 600 secrets/*.txt # .gitignore中添加 echo "secrets/" >> .gitignore echo ".env.production" >> .gitignore
<code"># .env.production 示例(敏感信息,不提交Git) APP_VERSION=1.2.3 NODE_ENV=production REDIS_PASSWORD=你的Redis密码 SMTP_HOST=smtp.yourdomain.com SMTP_USER=noreply@yourdomain.com SMTP_PASS=邮件密码
三、零停机更新策略
<code">#!/bin/bash
# /usr/local/bin/deploy-update.sh
# 新版本镜像推送后,执行此脚本零停机更新应用
set -e
APP_VERSION="${1:-latest}"
COMPOSE_FILE="/srv/myapp/docker-compose.yml"
echo "=== 开始部署版本:$APP_VERSION ==="
cd /srv/myapp
# 1. 拉取新镜像
APP_VERSION="$APP_VERSION" docker compose pull app
# 2. 滚动更新(新容器启动健康后,旧容器才下线)
APP_VERSION="$APP_VERSION" docker compose up -d \
--no-deps \
--build \
app
# 3. 等待健康检查通过
echo "等待新容器健康检查..."
timeout 120 bash -c 'until [ "$(docker compose ps app --format json | python3 -c "import sys,json; d=json.load(sys.stdin); print(d[\"Health\"])" 2>/dev/null)" = "healthy" ]; do sleep 5; done'
echo "✅ 部署成功:版本 $APP_VERSION"
# 4. 清理旧镜像(保留最近3个版本)
docker image prune -f四、日志管理与查看
<code"># 查看所有服务日志
docker compose logs -f
# 查看特定服务日志(最近100行)
docker compose logs --tail=100 app
# 查看特定时间段的日志
docker compose logs --since="2026-01-02T10:00:00" --until="2026-01-02T11:00:00" app
# 统计错误日志频率
docker compose logs app 2>&1 | grep -i "error" | \
awk '{print $1, $2}' | sort | uniq -c | sort -rn | head -20
# 导出日志到文件
docker compose logs --no-color app > /tmp/app-logs-$(date +%Y%m%d).log五、监控容器资源使用
<code"># 实时查看所有容器的CPU/内存使用
docker stats
# 查看特定容器详细信息
docker inspect 容器名称 | jq '.[0].State, .[0].HostConfig.Memory'
# 查看容器网络统计
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}"六、常用运维命令速查
<code"># 启动所有服务 docker compose up -d # 停止所有服务(保留数据) docker compose stop # 停止并删除容器(保留数据卷) docker compose down # 停止并删除所有内容(包括数据卷,危险!) docker compose down -v # 重启单个服务(不影响其他服务) docker compose restart app # 进入容器内部调试 docker compose exec app /bin/sh # 在容器内执行命令 docker compose exec mysql mysql -u root -p # 查看服务状态和健康 docker compose ps # 强制重建镜像并更新 docker compose up -d --force-recreate --build app
七、总结
生产级Docker Compose配置的核心要素:健康检查(确保依赖服务就绪)+ 密钥管理(Secrets替代环境变量)+ 日志限制(防止磁盘写满)+ 资源限制(防止单容器耗尽宿主机资源)。IDC.Net的香港VPS全系KVM架构,完整支持Docker的所有功能,是部署容器化应用的可靠基础平台。
版权声明:
作者:后浪云
链接:https://idc.net/help/442810/
文章版权归作者所有,未经允许请勿转载。
THE END
