目录
什么是 Docker Compose,为什么要使用它?
现代应用程序很少只运行在单个容器中。典型的电商系统需要 Web 服务器、数据库、缓存、队列 worker 和反向代理协同工作。Docker Compose 通过单个 YAML 文件定义和管理所有这些多容器应用。
| 对比项 | Docker (docker run) | Docker Compose |
|---|---|---|
| 容器数量 | 逐个管理 | 同时管理多个服务 |
| 网络 | 手动创建 | 自动创建项目网络 |
| 数据卷 | 通过参数指定 | 在 YAML 中声明 |
| 依赖关系 | 手动管理 | depends_on + healthcheck |
| 重启策略 | 每个容器单独设置 | YAML 中统一配置 |
Docker Compose 适合开发环境和单台 VPS 上的中小型生产部署。如需跨多台服务器扩展,可考虑 Docker Swarm 或 Kubernetes。
在 Ubuntu 上安装 Docker Engine 和 Docker Compose
推荐使用 Ubuntu 22.04 LTS 或 24.04 LTS 用于生产环境。
第一步 — 更新软件包并安装依赖
sudo apt update && sudo apt upgrade -y
sudo apt install -y ca-certificates curl gnupg lsb-release
第二步 — 添加 Docker GPG 密钥和软件源
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
第三步 — 安装 Docker Engine 和 Compose 插件
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
第四步 — 允许非 root 用户使用 Docker
sudo usermod -aG docker $USER
newgrp docker # 或退出后重新登录
验证安装
docker --version # Docker version 26.x.x
docker compose version # Docker Compose version v2.x.x
💡 注意
Docker Compose v2 使用
docker compose(无连字符)而非旧版的 docker-compose 命令。本文全程使用 v2 语法。
docker-compose.yml 文件结构
services: # 服务/容器列表
web: # 服务名(同时作为网络中的主机名)
image: nginx:alpine
ports:
- "80:80" # 宿主机端口:容器端口
volumes:
- ./html:/usr/share/nginx/html:ro
depends_on:
- app
restart: unless-stopped
app:
build: . # 从当前目录的 Dockerfile 构建
environment:
- NODE_ENV=production
env_file:
- .env
restart: unless-stopped
db:
image: postgres:16-alpine
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
restart: unless-stopped
volumes: # 命名卷(持久化存储)
pgdata:
示例:WordPress + MySQL + phpMyAdmin
mkdir ~/wordpress-stack && cd ~/wordpress-stack
# docker-compose.yml
services:
wordpress:
image: wordpress:6.7-php8.2-apache
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_NAME: ${MYSQL_DATABASE}
WORDPRESS_DB_USER: ${MYSQL_USER}
WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- wp_data:/var/www/html
depends_on:
mysql:
condition: service_healthy
restart: unless-stopped
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
phpmyadmin:
image: phpmyadmin:5-apache
ports:
- "8081:80"
environment:
PMA_HOST: mysql
depends_on:
- mysql
restart: unless-stopped
volumes:
wp_data:
mysql_data:
# .env(绝对不要提交到 Git)
MYSQL_ROOT_PASSWORD=StrongRootPass2026!
MYSQL_DATABASE=wordpress_db
MYSQL_USER=wpuser
MYSQL_PASSWORD=StrongUserPass2026!
docker compose up -d
docker compose ps
示例:Node.js + PostgreSQL + Redis
# docker-compose.yml
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
REDIS_URL: redis://redis:6379
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
restart: unless-stopped
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
redis:
image: redis:7-alpine
command: redis-server --save 20 1 --loglevel warning
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
volumes:
pg_data:
redis_data:
常用 Docker Compose 命令
| 命令 | 说明 |
|---|---|
docker compose up -d | 后台启动所有服务 |
docker compose down | 停止并删除容器(保留数据卷) |
docker compose down -v | 停止并删除容器和数据卷 |
docker compose ps | 查看所有服务状态 |
docker compose logs -f | 实时查看所有服务日志 |
docker compose logs -f web | 只查看 "web" 服务日志 |
docker compose exec app sh | 进入 "app" 容器的 shell |
docker compose restart | 重启所有服务 |
docker compose pull | 拉取最新镜像 |
docker compose build | 重新构建镜像 |
docker compose config | 验证并查看合并后的配置 |
网络与数据卷
网络
Docker Compose 自动为项目创建默认网络。同一文件中的所有服务都可以通过服务名作为主机名互相访问:
DATABASE_URL=postgresql://user:pass@postgres:5432/mydb
# ^^^^^^^ 服务名
⚠️ 安全提示
除非必要,不要将数据库端口(3306、5432)暴露给宿主机。尽量只在 Docker 内部网络中使用,并配合防火墙规则保护。
数据卷
- 命名卷(
pg_data:/var/lib/postgresql/data)——由 Docker 管理,持久化存储,推荐用于数据库 - 绑定挂载(
./src:/app/src)——将宿主机目录映射到容器,适合开发环境
使用 .env 文件安全管理密钥
Docker Compose 自动加载同目录下的 .env 文件,在 compose 文件中使用 ${变量名} 引用。
# .gitignore — 绝对不要提交 .env!
.env
*.env
!.env.example
💡 最佳实践
创建
.env.example 文件,包含变量名但不填写真实值,方便团队成员了解需要配置哪些变量。
生产环境最佳实践
1. 重启策略
restart: unless-stopped # 始终重启,除非手动 docker compose stop
2. 资源限制
deploy:
resources:
limits:
cpus: "0.5"
memory: 512M
reservations:
memory: 256M
3. 健康检查
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
4. Nginx 反向代理
推荐将 Nginx 作为单独服务或外部进程,负责反向代理和 SSL 证书(通过 Let's Encrypt/Certbot)。
5. 数据卷备份
docker run --rm \
-v wordpress-stack_mysql_data:/data \
-v $(pwd)/backup:/backup \
alpine tar czf /backup/mysql-$(date +%Y%m%d).tar.gz /data
常见问题排查
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 容器启动后立即退出 | 入口脚本错误或健康检查失败 | 运行 docker compose logs <服务名> |
| 端口已被占用 | 端口与其他进程冲突 | 运行 sudo ss -tlnp | grep 端口号 |
| 数据卷数据丢失 | 误执行了 down -v | 执行 down 前确认备份已完成 |
| 服务之间无法通信 | 服务不在同一网络 | 用 docker compose config 检查网络配置 |
| 数据卷权限被拒绝 | 容器与宿主机 UID/GID 不匹配 | 在服务中添加 user: "UID:GID" |
常见问题解答(FAQ)
Docker 和 Docker Compose 有什么区别?
Docker 通过命令行管理单个容器。Docker Compose 通过 YAML 文件同时管理多个容器,可以定义网络、数据卷和服务依赖关系,大大简化了多容器应用的管理。
运行 Docker Compose 需要多少内存?
运行 2-3 个服务(Web + 数据库 + 缓存)最低需要 2GB 内存。如果需要运行 5 个以上服务,建议使用 4GB 或更多内存。AsiaGB VPS 提供从 1GB 到 8GB 的多种规格可供选择。
docker-compose.yml 应该存放在哪里?
为每个项目创建独立目录(如 ~/myapp/),将 docker-compose.yml 和 .env 文件放在该目录中。将 compose 文件纳入 Git 管理,但绝对不要提交 .env 文件。
如何让 Docker Compose 在 VPS 重启后自动运行?
在 docker-compose.yml 的每个服务中添加
restart: unless-stopped。Docker Engine 会在系统启动时自动重启容器。如何更新 Docker Compose 中的镜像?
运行
docker compose pull 获取最新镜像,然后运行 docker compose up -d 用新镜像重新创建容器。未发生变化的服务不会被重启。Docker Compose 支持所有 Linux 发行版吗?
支持所有主流 Linux 发行版,包括 Ubuntu、Debian、CentOS 和 AlmaLinux。生产环境推荐使用 Ubuntu LTS,社区支持广泛,安全更新及时。
总结
Docker Compose 为在单台 VPS 上管理多容器应用提供了高效有序的方式。核心步骤:安装 Docker Engine 和 Compose 插件、编写 docker-compose.yml 定义服务、将密钥存储在 .env 文件中、添加重启策略确保容器在重启后自动恢复。
生产环境建议使用至少 2GB 内存和 SSD 存储的 VPS。AsiaGB 提供泰国和新加坡 VPS,配备 SSD 存储,99% 正常运行时间保证,价格实惠。