Docker Compose 入门
本教程共 25 篇 · 第 20 篇 · 更新于 2026-07-26 · 约 6 分钟阅读
20. Docker Compose 入门
本节目标:搞清楚 Compose 到底解决什么问题,看懂 compose.yaml 的骨架,能照着模板写出第一个多服务编排文件并跑起来。
为什么需要 Compose
前面几章你跑容器全靠 docker run,一两个容器还好。一旦要同时启动应用、数据库、缓存,命令就开始又长又难记。
举个真实场景:一个 Node 应用要连 MySQL,命令大概长这样。
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
--network todo-app \
-e MYSQL_HOST=mysql \
-e MYSQL_USER=root \
-e MYSQL_PASSWORD=secret \
-e MYSQL_DB=todos \
node:22-alpine \
sh -c "yarn install && yarn run dev"
这还只是应用本身,MySQL 还得再来一长串。换台机器部署?把这几条命令记到文档里,照着敲一遍,磕磕绊绊。
Docker Compose 就是为这事生的。它让你把所有容器和它们的配置写进一个 YAML 文件,一条命令拉起整套环境,一条命令拆掉。
TipCompose 是声明式工具:你只管定义「要什么样」,剩下交给它去协调。改了文件再跑一次
docker compose up,它会智能地只更新变化的部分。
Compose 是什么
Docker Compose 是一个定义和运行多容器应用的工具。核心就两件事:
- 用 YAML 文件描述应用栈(哪些服务、怎么连、用什么镜像)。
- 用一条命令把这些服务全部启动或停止。
它的工作场景覆盖开发、测试、CI,甚至轻量生产。不过最常见的还是本地开发环境——同事 clone 你的仓库,跑一条命令就能把整套依赖起来。
NoteDockerfile 和 Compose 文件别搞混。Dockerfile 教 Docker 怎么「造镜像」,Compose 文件描述「怎么跑容器」。很多项目里 Compose 文件会引用 Dockerfile 来构建某个服务的镜像。
compose.yaml 文件结构
Compose 文件默认叫 compose.yaml(也认 docker-compose.yml,老命名)。顶层有几个固定元素,最常用的三个:
services:定义有哪些服务(容器),必填。volumes:声明命名数据卷,可选。networks:声明自定义网络,可选。
一个最小骨架长这样。
services:
web:
image: nginx:alpine
db:
image: mysql:8.0
这就定义了两个服务 web 和 db,分别用官方的 nginx 和 mysql 镜像。是不是比刚才那串命令清爽多了?
NoteCompose 文件格式一直在演进,现在的版本不再需要在顶部写
version: "3"。Docker Engine 29.x 配套的 Compose 会自动识别 schema,写了反而报警告,直接从services:开始就好。
服务定义的常用字段
服务下面挂的就是各种配置项,它们基本都能在 docker run 里找到对应参数。下面这张表先混个眼熟,后面章节会挨个细讲。
| 字段 | 作用 | 对应 docker run 参数 |
|---|---|---|
image | 用哪个镜像 | 镜像名 |
build | 现场用 Dockerfile 构建 | docker build |
command | 覆盖默认启动命令 | 镜像名后的命令 |
ports | 端口映射 | -p |
volumes | 挂载数据卷或目录 | -v |
environment | 环境变量(键值对) | -e |
env_file | 从文件加载环境变量 | --env-file |
working_dir | 容器内工作目录 | -w |
depends_on | 依赖哪些服务先启动 | 无直接对应 |
restart | 重启策略 | --restart |
networks | 加入哪些网络 | --network |
第一个 compose 文件
来写一个真实能跑的。还是那个 Node + MySQL 的例子,把它整个搬到 Compose 里。
services:
app:
image: node:22-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
mysql:
image: mysql:8.0
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
逐段看一下:
app服务用node:22-alpine镜像,启动时先装依赖再跑 dev。端口把容器 3000 映射到宿主机 3000。working_dir指定容器内工作目录,volumes把当前目录挂进去,方便热重载。environment注入数据库连接信息,注意MYSQL_HOST的值是mysql——这就是下面那个服务的名字。mysql服务用mysql:8.0,把数据目录挂到命名卷todo-mysql-data,避免容器删了数据就没了。- 顶层的
volumes声明那个命名卷,Compose 才会自动帮你创建。
TipCompose 有个贴心特性:服务名会自动成为网络别名。
app想连数据库,直接用主机名mysql就行,不用记 IP。这是 Compose 自动建网络带来的好处。
自动建网络这个事
注意上面文件里我没写 networks。Compose 默认会为整个项目建一个 bridge 网络,把所有服务都塞进去。
这意味着:
- 服务之间能用服务名互相访问(自动 DNS 解析)。
- 外部默认访问不到内部服务,除非你显式
ports暴露端口。
跑起来后用 docker network ls 能看到一个叫 <项目名>_default 的网络。项目名默认是 compose.yaml 所在目录的名字(小写、连字符处理过)。
一条命令拉起
文件准备好,进入文件所在目录,跑:
docker compose up -d
-d 表示后台运行。你会看到类似输出:
[+] Running 3/3
✔ Network app_default Created 0.0s
✔ Container app-mysql-1 Started 0.4s
✔ Container app-app-1 Started 0.4s
一条命令,网络、卷、两个容器全到位。比之前一长串 docker run 爽多了。
用完想拆掉,同样一条命令:
docker compose down
[+] Running 3/3
✔ Container app-mysql-1 Removed 2.9s
✔ Container app-app-1 Removed 0.1s
✔ Network app_default Removed 0.1s
Warning
docker compose down默认只删容器和网络,不会删命名卷。这是有意为之——万一你想再启动,数据还在。如果你确定连数据一起清掉,加--volumes(简写-v):docker compose down --volumes
v2 语法别用错
这点要单独强调,因为网上很多老教程会带偏你。
Docker Compose 现在是 v2,命令是 docker compose(两个词,中间空格),集成在 Docker CLI 里。不是旧的 docker-compose(带连字符的独立 Python 脚本)。
# 正确(v2,推荐)
docker compose up -d
# 错误(v1,已淘汰)
docker-compose up -d
Docker Desktop 和新版 Docker Engine 都自带 v2,开箱即用,不用单独装。如果你敲 docker-compose 还能用,说明系统里残留了老的 Python 版本,建议卸了,统一用 docker compose。
小结
Compose 把多容器应用的「怎么跑」从一串命令挪到了一个 YAML 文件里。好处显而易见:
- 一条命令起、一条命令停。
- 文件进版本控制,团队共享同一套环境定义。
- 改了配置重跑,Compose 只动变化的部分。
下一章我们挨个过一遍 Compose 的常用命令和服务配置项,把这张表填满。