1. 项目概述:Docker Compose 的价值与应用场景
在现代化应用开发中,服务拆分成多个独立容器已成为主流架构模式。但随之而来的容器编排复杂度却让很多开发者头疼——如何管理这些容器之间的依赖关系?如何统一配置网络和存储?这正是 Docker Compose 要解决的核心问题。
我最初接触 Docker Compose 是在一个微服务项目中,当时需要同时启动 8 个相互依赖的服务容器。手动用 docker run 命令不仅繁琐,而且每次重启都要重新配置所有参数。直到发现 Docker Compose 这个神器,才真正体会到什么叫"一次配置,随处运行"的爽快感。
Docker Compose 通过 YAML 文件定义多容器应用的完整拓扑结构,包括:
- 服务容器及其镜像配置
- 容器间的网络连接方式
- 共享数据卷的挂载点
- 环境变量和依赖关系
这种声明式的配置方式特别适合以下场景:
- 开发环境标准化:团队新成员无需折腾环境,一条命令就能启动全套服务
- 微服务联调:轻松管理数十个相互依赖的服务容器
- CI/CD 流水线:确保测试环境与生产环境配置一致
- 本地 demo 演示:快速搭建包含前端、后端、数据库的完整演示环境
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心配置解析:docker-compose.yml 文件详解
2.1 基础结构剖析
一个标准的 docker-compose.yml 文件包含三大核心部分:
yaml复制version: '3.8' # 指定使用的 compose 版本
services: # 定义各个服务容器
web:
image: nginx:alpine
ports:
- "80:80"
db:
image: postgres:13
environment:
POSTGRES_PASSWORD: example
volumes: # 定义数据卷
db_data:
注意:version 字段虽然仍被支持,但在新版本中已非必需。建议使用最新语法而不声明版本。
2.2 服务配置关键参数
每个服务(service)下的配置项决定了容器的行为:
镜像相关:
yaml复制image: nginx:1.21 # 直接使用公共镜像
build: ./dir # 根据 Dockerfile 构建镜像
build:
context: .
dockerfile: Dockerfile.dev
args:
NODE_ENV: development
端口映射:
yaml复制ports:
- "8080:80" # 主机端口:容器端口
- "9000:9000/udp" # 指定 UDP 协议
expose:
- "3000" # 仅暴露给其他容器
环境变量:
yaml复制environment:
- DEBUG=1
- DATABASE_URL
env_file:
- .env
资源限制:
yaml复制deploy:
resources:
limits:
cpus: '0.50'
memory: 512M
reservations:
memory: 256M
2.3 网络与存储配置
自定义网络:
yaml复制networks:
app_net:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
services:
web:
networks:
- app_net
数据卷:
yaml复制volumes:
db_data: # 命名卷
./cache:/tmp/cache # 主机绑定挂载
services:
db:
volumes:
- db_data:/var/lib/postgresql/data
3. 实战案例:LNMP 环境编排
3.1 项目结构设计
我们以典型的 LNMP(Linux+Nginx+MySQL+PHP) 环境为例:
code复制lnmp-demo/
├── docker-compose.yml
├── nginx/
│ ├── conf.d/
│ │ └── app.conf
│ └── nginx.conf
├── php/
│ └── Dockerfile
└── www/
└── index.php
3.2 完整配置实现
yaml复制version: '3.8'
services:
nginx:
image: nginx:1.21-alpine
ports:
- "80:80"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./www:/var/www/html
depends_on:
- php
networks:
- app_network
php:
build: ./php
volumes:
- ./www:/var/www/html
networks:
- app_network
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: app_db
MYSQL_USER: app_user
MYSQL_PASSWORD: userpass
volumes:
- mysql_data:/var/lib/mysql
networks:
- app_network
volumes:
mysql_data:
networks:
app_network:
driver: bridge
3.3 PHP 服务 Dockerfile
dockerfile复制FROM php:7.4-fpm-alpine
RUN docker-php-ext-install pdo_mysql
RUN apk add --no-cache $PHPIZE_DEPS \
&& pecl install redis \
&& docker-php-ext-enable redis
WORKDIR /var/www/html
4. 高级管理技巧
4.1 多环境配置方案
方案一:继承式配置
code复制docker-compose.yml # 基础配置
docker-compose.override.yml # 开发环境配置(默认加载)
docker-compose.prod.yml # 生产环境配置
使用方式:
bash复制# 开发环境(自动加载 override)
docker-compose up
# 生产环境
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up
方案二:环境变量注入
yaml复制services:
app:
image: ${IMAGE_NAME:-nginx}:${IMAGE_TAG:-latest}
ports:
- "${HOST_PORT:-8080}:80"
通过 .env 文件或命令行参数覆盖默认值。
4.2 健康检查与依赖管理
yaml复制services:
web:
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
db:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 5
4.3 动态扩缩容
bash复制# 查看服务状态
docker-compose ps
# 扩展 web 服务实例数
docker-compose up --scale web=3 -d
# 查看日志
docker-compose logs -f web
5. 常见问题排查指南
5.1 容器启动顺序问题
症状:Web 服务启动时数据库还未就绪,导致连接失败
解决方案:
- 使用 healthcheck 配合 depends_on 条件
- 在应用代码中添加重试逻辑
- 使用 wait-for-it.sh 等工具脚本
yaml复制services:
web:
command: ["./wait-for-it.sh", "db:5432", "--", "npm", "start"]
5.2 端口冲突处理
症状:端口已被占用导致容器启动失败
排查步骤:
netstat -tulnp | grep <端口号>- 修改 compose 文件中的端口映射
- 或者停止占用端口的进程
5.3 数据卷权限问题
症状:容器内应用无法写入挂载的目录
解决方案:
- 主机目录设置合适权限
- 在 Dockerfile 中创建匹配的用户
- 使用 named volume 替代主机挂载
dockerfile复制RUN addgroup -g 1000 appuser && \
adduser -u 1000 -G appuser -D appuser
USER appuser
6. 性能优化实践
6.1 构建缓存优化
yaml复制services:
app:
build:
context: .
cache_from:
- myapp:latest
args:
- NODE_ENV=production
6.2 资源限制配置
yaml复制services:
redis:
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
reservations:
memory: 128M
6.3 日志管理策略
yaml复制services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
7. 安全最佳实践
7.1 最小权限原则
yaml复制services:
db:
user: "postgres"
read_only: true
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
7.2 敏感信息管理
方案一:Docker secrets
yaml复制services:
app:
secrets:
- db_password
secrets:
db_password:
file: ./secrets/db_password.txt
方案二:环境变量文件
bash复制# .env.prod
DB_PASSWORD=your_secure_password
7.3 镜像安全扫描
bash复制docker-compose build
docker scan myapp_image
8. 监控与日志收集
8.1 Prometheus 监控集成
yaml复制services:
node_exporter:
image: prom/node-exporter
ports:
- "9100:9100"
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
8.2 集中式日志收集
yaml复制services:
fluentd:
image: fluent/fluentd
volumes:
- ./fluent.conf:/fluentd/etc/fluent.conf
ports:
- "24224:24224"
app:
logging:
driver: "fluentd"
options:
tag: "app.log"
9. CI/CD 集成实践
9.1 GitHub Actions 集成示例
yaml复制name: CI
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: docker-compose up -d
- run: docker-compose exec -T app npm test
9.2 多阶段部署策略
yaml复制services:
app:
image: myapp:${TAG:-latest}
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
rollback_config:
parallelism: 0
delay: 0s
10. 扩展工具生态
10.1 可视化工具推荐
-
Portainer:轻量级容器管理 UI
bash复制
docker-compose -f portainer.yml up -d -
DockStation:桌面端容器管理工具
10.2 开发辅助工具
- docker-compose-watch:文件变更自动重建
- ctop:容器资源监控
- lazydocker:终端可视化工具
10.3 生产环境升级方案
对于生产环境,可以考虑:
- Docker Swarm:内置编排引擎
- Kubernetes:通过 Kompose 转换 compose 文件
- Nomad:灵活的调度器
bash复制# 转换为 Kubernetes 配置
kompose convert
在实际项目中,我通常会根据团队规模和技术栈选择合适的工具链。对于中小型项目,Docker Compose 已经能提供 80% 的编排需求。关键是要建立规范的配置管理流程,避免 compose 文件变成"祖传代码"。
