Docker Compose是Docker自动化部署中最常用的多容器编排工具。相比手写docker run命令,Compose通过声明式配置文件管理容器生命周期,在DevOps实践中承担着本地开发环境搭建和CI/CD流水线集成的核心角色。本文以一个Web应用+数据库+缓存的典型三容器架构为例,拆解Compose的配置方法和排障思路。
Docker Compose编排文件结构与核心配置
Compose文件使用YAML格式,顶层结构包含services、networks、volumes三大部分。一个典型的LNMP应用编排文件如下:
# docker-compose.yml
services:
web:
image: nginx:1.25-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./html:/usr/share/nginx/html:ro
- ./nginx/logs:/var/log/nginx
depends_on:
app:
condition: service_healthy
restart: unless-stopped
networks:
- frontend
app:
build: ./app
environment:
- DB_HOST=mysql
- DB_PORT=3306
- REDIS_HOST=redis
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
restart: unless-stopped
networks:
- frontend
- backend
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
MYSQL_DATABASE: appdb
volumes:
- mysql_data:/var/lib/mysql
- ./mysql/init:/docker-entrypoint-initdb.d:ro
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
restart: unless-stopped
networks:
- backend
redis:
image: redis:7-alpine
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- redis_data:/data
restart: unless-stopped
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true
volumes:
mysql_data:
redis_data:
这个配置的关键设计点在于网络隔离。frontend网络对外暴露80和443端口,backend网络标记为internal: true,外部无法直接访问MySQL和Redis容器。app容器同时接入两个网络,充当网关角色。
多容器网络隔离与通信方案
Docker Compose默认创建bridge网络。容器间通过服务名解析对方IP,DNS解析由Docker内置DNS服务器完成。上面的配置中,app容器可以通过mysql:3306连接数据库,通过redis:6379连接缓存,无需知道具体IP。
网络隔离的验证方法:
# 从web容器测试能否直连mysql(应该失败)
docker compose exec web ping mysql
# 输出: ping: bad address 'mysql'
# 从app容器测试连接mysql(应该成功)
docker compose exec app ping mysql
# 输出: 64 bytes from mysql (172.20.0.3): seq=1 ttl=64 time=0.123 ms
如果容器间无法通信,排查步骤:用docker network ls确认网络存在,用docker network inspect查看容器是否正确接入网络,用docker compose exec检查DNS解析是否正常。常见原因是容器没有加入同一个网络,或者depends_on配置导致启动顺序问题。
数据持久化与Volume挂载策略
Docker容器的文件系统是临时的,容器删除后数据丢失。数据持久化有三种方式:命名Volume、绑定挂载(Bind Mount)、tmpfs挂载。
命名Volume由Docker管理,适合数据库数据等不需要直接访问的场景。绑定挂载将宿主机目录映射到容器内,适合配置文件和日志等需要直接查看的场景。tmpfs挂载数据存放在内存中,适合临时文件。
# Volume备份脚本
#!/bin/bash
BACKUP_DIR="/data/backups/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
docker compose exec mysql mysqldump -u root -p"$DB_ROOT_PASS" appdb \
| gzip > "$BACKUP_DIR/appdb_$DATE.sql.gz"
# 保留最近7天备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete
绑定挂载的权限问题是最常见的坑。容器内进程以特定用户运行时,宿主机目录的权限可能不匹配。解决方法是在Dockerfile中创建与宿主机UID一致的用户,或者在docker-compose.yml中指定user参数。
环境变量管理与配置分离
敏感信息不应硬编码在Compose文件中。使用.env文件和变量引用实现配置分离:
# .env 文件
DB_ROOT_PASS=Str0ngP@ssw0rd
APP_SECRET=your-app-secret-key
MYSQL_VERSION=8.0
# docker-compose.yml 中引用
services:
mysql:
image: mysql:${MYSQL_VERSION}
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
.env文件不要提交到Git仓库,在.gitignore中排除。不同环境(开发、测试、生产)使用不同的.env文件。CI/CD流水线中通过环境变量注入生产环境的配置。
健康检查与自动重启机制
healthcheck配置让Docker能判断容器是否真正可用。上面的app容器配置了HTTP健康检查端点,每10秒检查一次。depends_on配合condition: service_healthy,确保app容器健康后web容器才启动。
restart策略的选择:always策略在容器退出后总是重启,包括手动stop后重启Docker时也会启动。unless-stopped策略在手动stop后不会自动启动,更适合需要人工干预的场景。no策略是默认值,容器退出后不重启。
# 查看容器健康状态
docker compose ps
# NAME STATUS PORTS
# web Up 2 minutes (healthy) 0.0.0.0:80->80/tcp
# app Up 3 minutes (healthy)
# mysql Up 3 minutes (healthy)
# redis Up 3 minutes (healthy)
# 查看健康检查日志
docker inspect --format='{{json .State.Health}}' app
Docker Compose在CI/CD流水线中的集成
在CI/CD流水线中,Docker Compose用于拉起测试环境,运行测试后销毁。典型的GitHub Actions配置:
# .github/workflows/test.yml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Start services
run: docker compose up -d
- name: Wait for healthy
run: |
timeout 60 bash -c 'until \
docker compose ps | grep -c "healthy" | grep -q 4; \
do sleep 2; done'
- name: Run tests
run: docker compose exec -T app npm test
- name: Tear down
if: always
run: docker compose down -v
日志收集方面,Docker Compose默认使用json-file日志驱动,日志无限制增长会撑满磁盘。生产环境需要配置日志轮转:
# docker-compose.yml 日志配置
services:
app:
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
或者切换到fluentd或syslog日志驱动,将日志统一发送到日志分析平台。监控告警体系可以对接cAdvisor采集容器指标,配合Prometheus + Grafana实现容器层面的监控可视化。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/dockercompose-duo-rong-qi-bian-pai-shi-zhan-zi-dong-hua-bu/