Docker Compose 实战指南:从入门到生产环境部署

· 阅读约需24分钟

一、引言

在现代软件开发中,容器化技术已经成为部署应用的标准方式。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 的优势

  1. 一键部署:通过单个命令启动整个应用栈
  2. 环境一致性:开发、测试、生产环境保持一致
  3. 可移植性:配置文件可在任何支持 Docker 的环境中运行
  4. 版本控制友好:YAML 配置文件易于版本管理
  5. 服务依赖管理:自动处理服务间的启动顺序

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:

后端 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 安全最佳实践

  1. 不要在配置文件中硬编码密码

    • 使用环境变量或 secrets 管理敏感信息
    • 不要将 .env 文件提交到版本控制
  2. 使用非 root 用户运行容器

services: app: image: myapp user: “1000:1000”

  1. 限制容器资源

services: app: image: myapp deploy: resources: limits: cpus: ‘0.50’ memory: 512M reservations: cpus: ‘0.25’ memory: 256M

  1. 使用只读文件系统

services: app: image: myapp read_only: true tmpfs:

  • /tmp

5.2 高可用与性能优化

  1. 服务副本与负载均衡

services: backend: image: myapp/backend deploy: replicas: 3 update_config: parallelism: 2 delay: 10s restart_policy: condition: on-failure

  1. 健康检查

services: backend: image: myapp/backend healthcheck: test: [“CMD”, “curl”, “-f”, “http://localhost:3000/health“] interval: 30s timeout: 10s retries: 3 start_period: 40s

  1. 日志管理

services: app: image: myapp logging: driver: “json-file” options: max-size: “10m” max-file: “3”

5.3 数据持久化与备份

  1. 使用命名卷而非绑定挂载

    • 命名卷性能更好,更易于管理
  2. 定期备份数据卷

备份 PostgreSQL 数据

docker-compose exec postgres pgdump -U postgres myapp > backup$(date +%Y%m%d).sql

  1. 数据库迁移策略
    • 应用启动前执行数据库迁移
    • 使用 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 都能提供优雅的解决方案。

在实际应用中,建议遵循以下原则:

  1. 从简单开始:先掌握基础用法,再逐步引入高级特性
  2. 保持配置简洁:避免过度设计,只配置真正需要的内容
  3. 重视安全:生产环境务必遵循安全最佳实践
  4. 自动化部署:结合 CI/CD 工具实现自动化部署流程
  5. 监控与日志:建立完善的监控和日志体系

随着容器化技术的发展,Docker Compose 也在不断演进。虽然在大规模集群场景下可能需要 Kubernetes 等更强大的编排工具,但对于大多数中小规模的应用,Docker Compose 仍然是最高效、最易用的选择。掌握 Docker Compose,将大大提升你的开发和部署效率。