结论先行:Docker Compose 把多容器应用栈(服务、内部网络、持久化数据卷、依赖顺序)固化为单个 compose.yaml 文件,一条 docker compose up -d 即可在全新 VPS 上一键拉起整套生产架构。单机环境下,十个以内的关联服务编排完全无需引入 Kubernetes 复杂度。生产落地盯死四点:弃用已废弃的 V1(带连字符的 docker-compose)、严禁在 YAML 明文硬编码密码(改用 .env 文件配合 .gitignore)、通过健康检查(healthcheck)配合 service_healthy 确保数据库真正就绪、持久化目录统一使用声明式命名卷。

全景图解导览:Docker Compose入门教程:从零编排多容器应用与… STAGE 01 · 问题起爆 写在前面 • 环节01:先敲命令手动创建 一个Docker桥接网络 • 环节02:运行docker run启… 定位核心风险卡点 STAGE 02 · 机制拆解 期望目标 • 拆解核心协议与准则 • 识别关键决策分水岭 • 识别关键决策分水岭 理清底层因果逻辑 STAGE 03 · 方案对照 技术架构与网络拓扑 • Docker Compose V1 vs V2 差异:很多旧教程依然在使… • Nginx+WordPress+MySQL… 对齐量化实测标尺 STAGE 04 · 工程落地 实操步骤 • 环境验证与Compose V2安 装:现代Linux系统上安装… • Compose YAML核心语法结… 锁死生产确定性

0、写在前面

在单容器时代,部署一套经典的 Web 应用流程繁琐且极易出错:

  1. 先敲命令手动创建一个 Docker 桥接网络;
  2. 运行 docker run 启动 MySQL 容器,手动挂载数据卷、输入一长串环境变量;
  3. 运行 docker run 启动 Web 应用容器,将其加入同一网络并配置端口映射;
  4. 运行 docker run 启动 Nginx 作为反向代理,手动挂载配置文件;
  5. 两个月后更换服务器或者新增开发成员时,若无精确笔记,这一长串参数很难完美复现。

任何一个端口号、环境变量或网络名称拼写错误,都会导致整个应用栈无法互通。

Docker Compose 是为了解决这种多容器协作问题而生的声明式工具。它通过结构化的 YAML 配置文件将所有服务、网络与存储关系全部代码化,实现「一份配置、处处秒级拉起」。

问题现场解剖:写在前面 ⚠️ 从问题出发:表面症状是如何一步步演变为生产故障或降权的? 独立开发者工具箱 · CH-33 · 核心卡点传导链 1. 环节01 先敲命令手动创建一个Docker 桥接网络 症结:认知偏差与配置盲区 2. 环节02 运行docker run启动MySQL容 器,手动挂载数据卷、输入一长… 传导:隐性劣化与边界失守 3. 环节03 运行docker run启动Web应用 容器,将其加入同一网络并配置… 破局:量化指标与工程验证 ✅ 破局核心原则(结论先行) Docker Compose把多容器应用栈(服务、内部网络、持久化数据卷、依赖顺序) 固化为单个compose.yaml文件,一条docker compose up-d即可在全新VPS上一…

1、期望目标

阅读并完成本文实操后,你将达成以下目标:

  • [ ] 掌握 Compose V2(Docker CLI 内置插件)的使用规范,彻底告别已淘汰的 V1 独立二进制;
  • [ ] 深入理解 services、networks、volumes 与 environment 核心语法;
  • [ ] 实操搭建一套生产级 Nginx + WordPress + MySQL 8.0 容器编排架构;
  • [ ] 掌握 .env 环境变量文件管理机制,杜绝数据库密码与密钥明文提交至 Git 仓库;
  • [ ] 掌握健康检查(Healthcheck)机制,彻底解决容器启动早于数据库导致连接报错的经典故障;
  • [ ] 熟练运用堆栈更新、热重启、指定服务重构与日志排障命令。
落地执行与验证流水线:期望目标 按序执行以下四步流程,把定性经验转化为可自动巡检的工程防线 STEP 01 基线探测与问题定位 采集真实线上指标与配置 快照 STEP 02 红线过滤与风险隔离 剔除高危配置与低质冗余 资产 STEP 03 标准化加固与重构 注入经过验证的脚本与架 构模板 STEP 04 持续监控与回归审计 接入定时巡检防止问题二 次复发

2、技术架构与网络拓扑

Docker Compose V1 vs V2 差异

很多旧教程依然在使用带有中划线的 docker-compose 命令,这一版本已在 2023 年 6 月正式到达生命周期终点(EOL)。

评估维度 Docker Compose V1(已淘汰) Docker Compose V2(当前标准)
调用命令 docker-compose(带连字符) docker compose(中间为空格)
底层实现 基于 Python 编写的独立二进制文件 基于 Go 语言重写,原生内置于 Docker CLI
版本规范 顶部强制声明 version: '3.8' 等版本号 遵循统一 Compose Spec,无需声明顶层 version
执行性能 命令解析启动慢,多容器并发拉取效率低 启动执行速度提升约 30%,错误栈定位更精准
高级特性 不支持现代语法特性 原生支持 watch 热更新、环境检查与配置校验

Nginx + WordPress + MySQL 网络拓扑

在默认情况下,Docker Compose 会自动为项目创建独立的自定义网桥。容器之间无需对外暴露数据库端口,只需使用服务名即可在内网中通过内置 DNS 实现安全通信。

外部访客 HTTP / HTTPS Docker Compose 自定义隔离网络 (内部 DNS 自动解析) 服务名: nginx 开放端口: 80 / 443 挂载 ./nginx/conf.d 反向代理与静态缓冲 服务名: wordpress 内网端口: 80 (无外网) 挂载 wp_data 命名卷 PHP-FPM / 业务运行时 服务名: db 内网端口: 3306 (隔离) 挂载 db_data 命名卷 内置 Healthcheck 就绪探针

3、实操步骤

3.1 环境验证与 Compose V2 安装

现代 Linux 系统上安装 Docker 时已默认自带 Compose 插件。首先在终端运行验证:

1
docker compose version

若能正确输出形如 Docker Compose version v2.29.x 的版本信息,即可直接使用。

若提示 compose is not a docker command,表明当前 Docker 引擎版本过老或缺少插件。推荐使用 ITTinker 开源的生产级部署脚本直接修复安装:

1
2
# 一键安装最新的官方 Docker CE 与 Docker Compose V2 插件
curl -fsSL https://raw.githubusercontent.com/ittinker-team/ittinker-scripts/main/docker-quick-deploy/deploy.sh | sudo bash

3.2 Compose YAML 核心语法结构

官方 Compose 文件标准命名为 compose.yaml(兼容历史习惯的 docker-compose.yml)。一个标准文件的顶层通常包含三个核心段落:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 1. 服务定义(每一个子项代表一个独立的容器)
services:
app:
image: node:20-alpine # 锁定明确版本号
container_name: my-app # 自定义容器名称
restart: unless-stopped # 生产级开机自启策略
ports:
- "3000:3000" # 宿主端口:容器端口
environment:
- NODE_ENV=production # 注入环境变量
env_file:
- .env # 从外部 .env 读取敏感数据
volumes:
- ./data:/app/data # 挂载绑定目录
- app_cache:/app/cache # 挂载独立命名卷
networks:
- frontend-net # 加入指定内部网络
depends_on:
db:
condition: service_healthy # 关键:必须等待数据库健康就绪才拉起应用

# 2. 持久化数据卷声明
volumes:
app_cache: # 命名卷由 Docker 自动管理宿主存储路径

# 3. 自定义网络声明
networks:
frontend-net:
driver: bridge # 桥接驱动,实现内网 DNS 服务发现

3.3 实战:编排生产级 Nginx + WordPress + MySQL 8.0 架构

下面通过实战编排一套开箱即用的海外 WordPress 站点。项目包含三个服务:

  • db:MySQL 8.0 数据库,数据卷持久化,配置健康检查;
  • wordpress:核心应用容器,依赖 db 的健康状态;
  • nginx:前端反向代理,挂载宿主反代配置,只开放 80/443 给外部访问。

步骤 1:规划项目目录

1
2
mkdir -p ~/deploy-wordpress/{nginx/conf.d,html}
cd ~/deploy-wordpress

步骤 2:创建环境变量文件 .env

敏感密码严禁写在 YAML 文件中。我们在同级目录创建 .env:

1
2
3
4
5
6
7
8
9
10
cat > .env <<'EOF'
# MySQL 数据库认证信息
MYSQL_DATABASE=wordpress_db
MYSQL_USER=wp_user
MYSQL_PASSWORD=SuperStrongUserPassword2026!
MYSQL_ROOT_PASSWORD=RootAdminSecretPassword2026!

# Nginx 端口规划
WEB_PORT=80
EOF

将 .env 加入本地版本控制黑名单:

1
echo ".env" >> .gitignore

步骤 3:编写 nginx.conf 反代配置

创建 nginx/conf.d/default.conf:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 80;
server_name localhost;

client_max_body_size 64M;

location / {
proxy_pass http://wordpress:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

步骤 4:编写生产级 compose.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
cat > compose.yaml <<'EOF'
services:
# 1. 数据库服务
db:
image: mysql:8.0.36
container_name: wp-db
restart: unless-stopped
environment:
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
volumes:
- db_data:/var/lib/mysql
# 关键配置:定义健康探针,每 5 秒用 mysqladmin 验证一次存活
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
interval: 5s
timeout: 5s
retries: 10
start_period: 15s

# 2. WordPress 业务核心
wordpress:
image: wordpress:6.5-php8.2-fpm-alpine
container_name: wp-app
restart: unless-stopped
depends_on:
db:
condition: service_healthy # 仅当 MySQL 真正可以通过 ping 校验后才启动
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_NAME: ${MYSQL_DATABASE}
WORDPRESS_DB_USER: ${MYSQL_USER}
WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- wp_data:/var/www/html

# 3. 前端反向代理网关
nginx:
image: nginx:1.25-alpine
container_name: wp-web
restart: unless-stopped
ports:
- "${WEB_PORT}:80"
volumes:
- wp_data:/var/www/html:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
depends_on:
- wordpress

# 持久化存储定义
volumes:
db_data:
wp_data:
EOF

3.4 堆栈生命周期管理指令

进入项目所在目录(即 compose.yaml 所在的目录),执行以下管理指令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 1. 启动并后台运行全部服务(若镜像不存在会自动并行拉取)
docker compose up -d

# 2. 查看当前堆栈中各服务的运行状态、端口绑定与健康检查情况
docker compose ps

# 3. 实时跟踪所有容器合并输出的标准日志
docker compose logs -f

# 4. 只查看特定服务(如 db)的实时日志
docker compose logs -f db

# 5. 校验当前 compose.yaml 配置文件的语法正确性,并打印解析后的完整配置
docker compose config

# 6. 单独平滑重启某一个服务(例如修改了 Nginx 反代配置)
docker compose restart nginx

# 7. 拉取最新镜像并无缝重建服务(代码或镜像版本升级时使用)
docker compose pull
docker compose up -d

# 8. 停止并移除容器和内部网络(数据卷不受任何影响,业务数据安全留存)
docker compose down

# 9. 彻底清空容器、网络以及数据卷(高危警告:这将直接抹除数据库与文件!)
# 仅在需要完全重置开发测试环境时使用:
docker compose down -v
落地执行与验证流水线:实操步骤 按序执行以下四步流程,把定性经验转化为可自动巡检的工程防线 STEP 01 环境验证与Compose… 现代Linux系统上安装 Docker时已默认自带… STEP 02 Compose YAML核心语… 官方Compose文件标准命 名为compose.yaml(兼… STEP 03 实战:编排生产级… 下面通过实战编排一套开 箱即用的海外WordPress… STEP 04 堆栈生命周期管理指令 进入项目所在目录(即 compose.yaml所在的目…

4、生产避坑指南与排障速查

避坑 1:depends_on 未配置健康探针引发「数据库连接拒绝」

  • 现象:执行 docker compose up -d 后,wordpress 容器报错退出,日志显示 Error establishing a database connection 或 Connection refused。
  • 根因:基础语法中的 depends_on: [db] 仅仅意味着「Docker 在启动 wordpress 前先给 db 发送创建指令」。然而 MySQL 容器启动后,内部需要花费 10 至 30 秒执行首次数据目录初始化与权限刷新。此时应用去连接数据库,端口未就绪,引发崩溃。
  • 解法:必须如本文示例,在 db 服务中编写 healthcheck,并在应用层声明 condition: service_healthy。

避坑 2:容器内部通信误用 localhost

  • 现象:Node.js 或 WordPress 报错 connect ECONNREFUSED 127.0.0.1:3306。
  • 根因:在默认的 Bridge 网络下,每个容器都拥有独立的 Network Namespace。容器内的 localhost 或 127.0.0.1 指向容器本身,而非宿主机或其他容器。
  • 解法:在网络互联时,连接目标必须填写服务名称(例如 db、redis),Docker 内部 DNS 会自动将其解析为对应容器的内网 IP。

避坑 3:.env 文件等号周围带有非法空格

  • 现象:环境变量解析出的值带有前缀空格,例如实际读到 " db" 而不是 "db",导致认证持续失败。
  • 根因:Docker Compose 对 .env 的解析规则要求键值对中间不得插入无意义的空格。
  • 规范写法:
    1
    2
    3
    4
    5
    6
    7
    # 错误格式(禁止加空格)
    DB_HOST = db
    DB_PASS = 123456

    # 正确格式
    DB_HOST=db
    DB_PASS=123456
问题现场解剖:生产避坑指南与排障速查 ⚠️ 从问题出发:表面症状是如何一步步演变为生产故障或降权的? 独立开发者工具箱 · CH-33 · 核心卡点传导链 1. 现象 执行docker compose up-d 后,wordpress容器报错退… 症结:认知偏差与配置盲区 2. 根因 基础语法中的dependson:[db] 仅仅意味着「Docker在启动… 传导:隐性劣化与边界失守 3. 解法 必须如本文示例,在db服务中 编写healthcheck,并在应用… 破局:量化指标与工程验证 ✅ 破局核心原则(结论先行) Docker Compose把多容器应用栈(服务、内部网络、持久化数据卷、依赖顺序) 固化为单个compose.yaml文件,一条docker compose up-d即可在全新VPS上一…

5、FAQ(高频问题解答)

Q1:新建的 compose.yaml 文件还需要写顶层 version: '3.8' 吗?

不需要。自 Docker Compose V2 统一采用 Compose Specification 规范以来,顶层 version 字段已被废弃。保留该字段会触发运行时警告,新项目直接从 services: 段落开始书写即可。

Q2:修改了代码或者某一个服务的配置,必须全部重启吗?

不需要。运行以下命令即可针对单一服务进行差异化更新:

1
2
# 只重新构建并热重载名为 app 的单一容器,其他正在运行的 db 与 redis 不受任何影响
docker compose up -d --no-deps --build app

Q3:一台 VPS 上管理多个独立项目,Compose 的网络会冲突吗?

不会。Docker Compose 默认使用当前项目所在目录名作为堆栈前缀(例如目录名为 proj-a,创建的网络会自动命名为 proj-a_default)。不同目录下的项目默认彼此网络隔离,只要宿主机对外映射的端口不发生冲突,多个堆栈即可和谐共存。

底层机制与架构拆解:FAQ(高频问题解答) 四阶段递进分析模型 · 从前置识别到最终工程定级 S1 输入识别与场景分流 明确核心业务诉求与上下 文边界条件 S2 底层协议与规则校验 对照核心规范与真实负载 指标逐项核验 S3 瓶颈隔离与风险阻断 剔除干扰链路、单点隐患 与高危配置 S4 确定性架构标准输出 沉淀为可一键复现的工程 配置基线 💡 工程启示:任何一个前置环节失守,都会通过传导链放大为下游的系统性偏差