Docker Compose 实战指南:从入门到生产环境部署
一、引言
在现代软件开发中,容器化技术已经成为部署应用的标准方式。Docker 作为最流行的容器化平台,极大地简化了应用的打包和部署流程。然而,当应用由多个服务组成时,单独管理每个容器的启动、网络和依赖关系变得复杂而繁琐。这就是 Docker Compose 发挥作用的地方。
Docker Compose 是 Docker 官方提供的容器编排工具,它允许你通过一个 YAML 文件来定义和运行多容器 Docker 应用。只需一条命令,你就可以创建并启动配置文件中定义的所有服务。本文将带你从 Docker Compose 的基础概念出发,逐步深入到生产环境的部署实践,帮助你全面掌握这一强大工具。
二、Docker Compose 基础概念
2.1 什么是 Docker Compose
Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,你可以使用 YAML 文件来配置应用程序的服务,然后使用单个命令创建并启动所有服务。
Compose 的核心概念包括:
- 服务(Service):一个服务代表一个容器,它可以运行特定镜像的一个或多个实例。
- 项目(Project):由一组关联的服务组成的完整应用,通常对应一个 docker-compose.yml 文件。
- 卷(Volume):用于持久化数据的 Docker 卷。
- 网络(Network):服务之间通信的网络层。
2.2 Docker Compose 的优势
- 一键部署:通过单个命令启动整个应用栈
- 环境一致性:开发、测试、生产环境保持一致
- 可移植性:配置文件可在任何支持 Docker 的环境中运行
- 版本控制友好:YAML 配置文件易于版本管理
- 服务依赖管理:自动处理服务间的启动顺序
2.3 安装 Docker Compose
Docker Compose 通常随 Docker Desktop 一起安装。如果你使用的是 Linux 系统,可以通过以下命令安装:
下载 Docker Compose
sudo curl -L “https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)” -o /usr/local/bin/docker-compose
添加执行权限
sudo chmod +x /usr/local/bin/docker-compose
验证安装
docker-compose –version
对于 Docker Compose V2(推荐),它已集成到 Docker CLI 中,可以通过 docker compose 命令直接使用。
三、Docker Compose 实战入门
3.1 第一个 docker-compose.yml 文件
让我们从一个简单的 Web 应用开始。假设我们要运行一个 Nginx Web 服务器:
version: ‘3.8’
services: web: image: nginx:latest ports:
- “8080:80” volumes:
- ./html:/usr/share/nginx/html restart: always
这个配置文件定义了:
- 使用 Nginx 最新版本镜像
- 将主机的 8080 端口映射到容器的 80 端口
- 将本地 ./html 目录挂载到容器的网页根目录
- 容器总是自动重启
启动服务: docker-compose up -d
3.2 多服务应用:WordPress 示例
下面是一个更实际的例子——使用 Docker Compose 部署 WordPress:
version: ‘3.8’
services: db: image: mysql:8.0 volumes:
- db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: example_root_password MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: example_password
wordpress: depends_on:
- db image: wordpress:latest ports:
- “8000:80” restart: always environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: example_password WORDPRESS_DB_NAME: wordpress volumes:
- wordpress_data:/var/www/html
volumes: db_data: wordpress_data:
这个配置包含两个服务:
- db:MySQL 数据库服务,使用命名卷持久化数据
- wordpress:WordPress 应用,依赖 db 服务,通过环境变量配置数据库连接
启动命令: docker-compose up -d
3.3 常用命令
启动服务(后台运行)
docker-compose up -d
查看服务状态
docker-compose ps
查看服务日志
docker-compose logs -f
停止服务
docker-compose stop
停止并删除容器、网络
docker-compose down
停止并删除容器、网络、卷
docker-compose down -v
重新构建镜像
docker-compose build
拉取最新镜像
docker-compose pull
四、进阶实战:微服务架构部署
4.1 项目结构
让我们构建一个典型的微服务架构,包含前端、后端 API、数据库和缓存:
myapp/ ├── docker-compose.yml ├── .env ├── frontend/ │ └── Dockerfile ├── backend/ │ └── Dockerfile └── nginx/ └── nginx.conf
4.2 完整的 docker-compose.yml 配置
version: ‘3.8’
services:
Nginx 反向代理
nginx: image: nginx:alpine ports:
- “80:80”
- “443:443” volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro depends_on:
- frontend
- backend restart: unless-stopped networks:
- frontend_network
- backend_network
前端应用
frontend: build: ./frontend restart: unless-stopped networks:
- frontend_network environment:
- NODE_ENV=production
- API_URL=http://backend:3000
后端 API 服务
backend: build: ./backend restart: unless-stopped depends_on:
- postgres
- redis networks:
- frontend_network
- backend_network
- database_network environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://postgres:${DB_PASSWORD}@postgres:5432/myapp
- REDIS_URL=redis://redis:6379 env_file:
- .env
PostgreSQL 数据库
postgres: image: postgres:15-alpine restart: unless-stopped volumes:
- postgres_data:/var/lib/postgresql/data networks:
- database_network environment:
- POSTGRES_DB=myapp
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=${DB_PASSWORD} env_file:
- .env
Redis 缓存
redis: image: redis:7-alpine restart: unless-stopped volumes:
- redis_data:/data networks:
- database_network command: redis-server –appendonly yes
网络配置
networks: frontend_network: driver: bridge backend_network: driver: bridge database_network: driver: bridge
数据卷
volumes: postgres_data: redis_data:
4.3 环境变量文件 .env
使用 .env 文件管理敏感信息和环境配置:
数据库配置
DB_PASSWORD=your_secure_password_here
应用配置
APP_PORT=3000 NODE_ENV=production
JWT 密钥
JWT_SECRET=your_jwt_secret_key_here
4.4 Nginx 反向代理配置
events { worker_connections 1024; }
http { upstream frontend { server frontend:3000; }
upstream backend {
server backend:3000;
}
server {
listen 80;
server_name example.com;
# 前端路由
location / {
proxy_pass http://frontend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# API 路由
location /api/ {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
rewrite /api/(.*) /$1 break;
}
}}
五、生产环境部署最佳实践
5.1 安全最佳实践
不要在配置文件中硬编码密码
- 使用环境变量或 secrets 管理敏感信息
- 不要将 .env 文件提交到版本控制
使用非 root 用户运行容器
services: app: image: myapp user: “1000:1000”
- 限制容器资源
services: app: image: myapp deploy: resources: limits: cpus: ‘0.50’ memory: 512M reservations: cpus: ‘0.25’ memory: 256M
- 使用只读文件系统
services: app: image: myapp read_only: true tmpfs:
- /tmp
5.2 高可用与性能优化
- 服务副本与负载均衡
services: backend: image: myapp/backend deploy: replicas: 3 update_config: parallelism: 2 delay: 10s restart_policy: condition: on-failure
- 健康检查
services: backend: image: myapp/backend healthcheck: test: [“CMD”, “curl”, “-f”, “http://localhost:3000/health“] interval: 30s timeout: 10s retries: 3 start_period: 40s
- 日志管理
services: app: image: myapp logging: driver: “json-file” options: max-size: “10m” max-file: “3”
5.3 数据持久化与备份
使用命名卷而非绑定挂载
- 命名卷性能更好,更易于管理
定期备份数据卷
备份 PostgreSQL 数据
docker-compose exec postgres pgdump -U postgres myapp > backup$(date +%Y%m%d).sql
- 数据库迁移策略
- 应用启动前执行数据库迁移
- 使用 init container 模式
5.4 CI/CD 集成
使用 Docker Compose 进行 CI/CD 流水线的示例:
.gitlab-ci.yml 示例
stages:
- build
- test
- deploy
build: stage: build script:
- docker-compose build
test: stage: test script:
- docker-compose -f docker-compose.test.yml up –abort-on-container-exit
deploy: stage: deploy script:
- docker-compose pull
- docker-compose up -d only:
- main
六、常见问题与解决方案
6.1 服务启动顺序问题
虽然 depends_on 可以控制启动顺序,但它不会等待服务”就绪”。推荐使用等待脚本:
#!/bin/bash
wait-for-it.sh
set -e
host=”$1″ shift port=”$1″ shift
until nc -z “$host” “$port”; do echo “Waiting for $host:$port…” sleep 1 done
exec “$@”
在 Dockerfile 中使用:
COPY wait-for-it.sh /wait-for-it.sh RUN chmod +x /wait-for-it.sh ENTRYPOINT [“/wait-for-it.sh”, “db”, “5432”, “–“, “npm”, “start”]
6.2 镜像版本管理
- 避免使用 latest 标签,使用具体版本号
- 生产环境使用固定的镜像摘要(digest)
- 建立自己的镜像仓库进行版本管理
6.3 网络问题排查
查看网络
docker network ls
查看网络详情
docker network inspect myapp_default
测试服务间连通性
docker-compose exec backend ping db
七、总结
Docker Compose 是一个强大而灵活的工具,它简化了多容器应用的部署和管理。从简单的单页应用到复杂的微服务架构,Compose 都能提供优雅的解决方案。
在实际应用中,建议遵循以下原则:
- 从简单开始:先掌握基础用法,再逐步引入高级特性
- 保持配置简洁:避免过度设计,只配置真正需要的内容
- 重视安全:生产环境务必遵循安全最佳实践
- 自动化部署:结合 CI/CD 工具实现自动化部署流程
- 监控与日志:建立完善的监控和日志体系
随着容器化技术的发展,Docker Compose 也在不断演进。虽然在大规模集群场景下可能需要 Kubernetes 等更强大的编排工具,但对于大多数中小规模的应用,Docker Compose 仍然是最高效、最易用的选择。掌握 Docker Compose,将大大提升你的开发和部署效率。