目录

Docker Compose 教程:用一个文件管理多个容器

一个真实的应用通常不止一个容器:网站、数据库、缓存……每个都要记住一长串 docker run 参数,还要先创建网络、Volume,并注意启动顺序。

Docker Compose 让你把这些配置写进一个 YAML 文件,然后用一条命令全部启动:

docker compose up -d

安装与版本

  • Docker Desktop(Windows、macOS)已内置 Compose。
  • Linux:按照安装 Docker中的步骤安装 docker-compose-plugin 即可。
$ docker compose version
Docker Compose version v5.6.0

旧版独立程序叫 docker-compose(中间有连字符,v1),已经停止维护;现在请使用 docker compose(空格)。Compose 的版本号从 v2 直接跳到 v5,用法没有改变。网上的旧教程会混用两者,命令和参数大致相同。

示例项目:网站 + 数据库 + 管理界面

创建文件夹 compose-demo,结构如下:

compose-demo/
├── compose.yaml
└── site/
    └── index.html

在 site/index.html 中放一个简单的网页(内容随意)。compose.yaml:

services:
  web:
    image: nginx:1.30-alpine
    ports:
      - "8080:80"
    volumes:
      - ./site:/usr/share/nginx/html:ro

  db:
    image: postgres:18
    environment:
      POSTGRES_PASSWORD: example
    volumes:
      - pgdata:/var/lib/postgresql

  adminer:
    image: adminer
    ports:
      - "8081:8080"
    depends_on:
      - db

volumes:
  pgdata:

三个服务:

服务作用
webnginx,把 ./site 文件夹用作网站,主机端口 8080
dbPostgreSQL 18,数据保存在名为 pgdata 的 Volume 中(注意 18 版挂载的是 /var/lib/postgresql,参见 Volume)
adminer网页版数据库管理工具,主机端口 8081

如果用 docker run 编写相同的配置,需要先运行 docker network create、docker volume create,再执行三条很长的 docker run 命令。

启动:docker compose up

在 compose-demo 文件夹中运行:

$ docker compose up -d
[+] up 34/34
 ✔ Image nginx:1.30-alpine          Pulled                                                      7.8s
 ✔ Image adminer                    Pulled                                                      8.7s
 ✔ Network compose-demo_default     Created                                                     0.1s
 ✔ Volume compose-demo_pgdata       Created                                                     0.0s
 ✔ Container compose-demo-web-1     Started                                                     1.7s
 ✔ Container compose-demo-db-1      Started                                                     0.8s
 ✔ Container compose-demo-adminer-1 Started                                                     1.0s

一条命令就完成了:下载镜像(Pulled,只有第一次会出现)、创建网络和 Volume、启动三个容器。

$ docker compose ps
NAME                     IMAGE               COMMAND                  SERVICE   CREATED          STATUS          PORTS
compose-demo-adminer-1   adminer             "entrypoint.sh docke…"   adminer   10 seconds ago   Up 9 seconds    0.0.0.0:8081->8080/tcp, [::]:8081->8080/tcp
compose-demo-db-1        postgres:18         "docker-entrypoint.s…"   db        10 seconds ago   Up 10 seconds   5432/tcp
compose-demo-web-1       nginx:1.30-alpine   "/docker-entrypoint.…"   web       10 seconds ago   Up 9 seconds    0.0.0.0:8080->80/tcp, [::]:8080->80/tcp

$ docker network ls --filter name=compose-demo
NETWORK ID     NAME                   DRIVER    SCOPE
a722da926fbd   compose-demo_default   bridge    local

$ docker volume ls --filter name=compose-demo
DRIVER    VOLUME NAME
local     compose-demo_pgdata
  • 容器名称的格式是 项目名称-服务名称-编号。项目名称默认是文件夹名称(compose-demo),因此不同文件夹中的项目不会互相干扰。
  • Compose 自动创建了 compose-demo_default 网络,三个服务都在其中,可以通过服务名称互相连接。
  • pgdata Volume 的实际名称是 compose-demo_pgdata。
  • db 没有设置 ports,因此 PORTS 列只有 5432/tcp,外部无法访问它。

打开 http://localhost:8080:

Compose 启动的 nginx 显示 site/index.html
web 服务显示 site/index.html 的内容

使用 Adminer 管理数据库

打开 http://localhost:8081,就会看到 Adminer 登录界面。注意 System 默认是 MySQL:

Adminer 登录界面中 System 默认是 MySQL
Adminer 的默认设置:System 为 MySQL / MariaDB,Server 已自动填入 db

按照以下设置登录:

字段填写内容
SystemPostgreSQL(一定要修改,否则会尝试用 MySQL 的方式连接并失败)
Serverdb(服务名称,通过 Compose 网络解析)
Usernamepostgres
Passwordexample(compose.yaml 中的 POSTGRES_PASSWORD)
Adminer 登录界面,System 选择 PostgreSQL
将 System 改为 PostgreSQL 后,点击 Login

登录成功后,界面会显示 PostgreSQL 的版本和数据库列表:

Adminer 登录后显示 PostgreSQL 版本和数据库列表
Adminer 通过 Compose 网络连接到 db 服务中的 PostgreSQL

点击左侧的 SQL command,输入 SQL:

CREATE TABLE guestbook (id serial PRIMARY KEY, name text, message text);
INSERT INTO guestbook (name, message) VALUES ('Docker', 'Hello from Compose!');
SELECT * FROM guestbook;
Adminer SQL command 输入界面
在 SQL command 中输入 SQL,然后点击 Execute

点击 Execute,三条命令会依次执行,最后的 SELECT 会列出刚才新增的数据:

Adminer 执行 SQL 的结果
创建数据表、添加一条数据并查看查询结果

查看日志

$ docker compose logs --tail 2
web-1  | 2026/10/13 00:14:23 [notice] 1#1: start worker processes
web-1  | 2026/10/13 00:14:23 [notice] 1#1: start worker process 30
db-1   | 2026-10-13 00:14:24.205 UTC [71] LOG:  database system was shut down at 2026-10-13 00:14:24 UTC
db-1   | 2026-10-13 00:14:24.210 UTC [1] LOG:  database system is ready to accept connections
adminer-1  | [Tue Oct 13 00:14:22 2026] PHP 8.4.26 Development Server (http://[::]:8080) started

docker compose logs 会合并显示所有服务的日志,每行前面都会标明对应的服务。--tail 2 只显示每个服务最后 2 行,-f 会持续跟踪,docker compose logs db 则只查看 db。

停止与启动

$ docker compose stop
[+] stop 3/3
 ✔ Container compose-demo-adminer-1 Stopped                                                     0.4s
 ✔ Container compose-demo-web-1     Stopped                                                     0.4s
 ✔ Container compose-demo-db-1      Stopped                                                     0.3s

$ docker compose ps -a
NAME                     IMAGE               COMMAND                  SERVICE   CREATED          STATUS                              PORTS
compose-demo-adminer-1   adminer             "entrypoint.sh docke…"   adminer   53 seconds ago   Exited (0) Less than a second ago
compose-demo-db-1        postgres:18         "docker-entrypoint.s…"   db        53 seconds ago   Exited (0) Less than a second ago
compose-demo-web-1       nginx:1.30-alpine   "/docker-entrypoint.…"   web       53 seconds ago   Exited (0) Less than a second ago

$ docker compose start
[+] start 3/3
 ✔ Container compose-demo-db-1      Started                                                     0.3s
 ✔ Container compose-demo-web-1     Started                                                     1.0s
 ✔ Container compose-demo-adminer-1 Started                                                     0.4s

stop 只会停止容器(Exited (0)),容器、网络和 Volume 都还在;start 可以重新启动它们。

down:删除容器,但保留数据

$ docker compose down
[+] down 4/4
 ✔ Container compose-demo-adminer-1 Removed                                                     0.7s
 ✔ Container compose-demo-web-1     Removed                                                     0.7s
 ✔ Container compose-demo-db-1      Removed                                                     0.3s
 ✔ Network compose-demo_default     Removed                                                     0.1s

down 删除了容器和网络,但不会删除 Volume。重新运行 up,数据仍然在:

$ docker compose up -d
[+] up 4/4
 ✔ Network compose-demo_default     Created                                                     0.1s
 ✔ Container compose-demo-web-1     Started                                                     0.7s
 ✔ Container compose-demo-db-1      Started                                                     1.1s
 ✔ Container compose-demo-adminer-1 Started                                                     1.6s

$ docker compose exec db psql -U postgres -c "SELECT * FROM guestbook;"
 id |  name  |       message
----+--------+---------------------
  1 | Docker | Hello from Compose!
(1 row)

down -v:连数据一起删除

$ docker compose down -v
[+] down 5/5
 ✔ Container compose-demo-adminer-1 Removed                                                     0.7s
 ✔ Container compose-demo-web-1     Removed                                                     0.7s
 ✔ Container compose-demo-db-1      Removed                                                     0.2s
 ✔ Volume compose-demo_pgdata       Removed                                                     0.1s
 ✔ Network compose-demo_default     Removed                                                     0.1s

加上 -v 会同时删除 compose-demo_pgdata Volume,数据库中的数据也就没了。在生产环境中请谨慎使用 down -v。

基本操作汇总

docker compose up -d        # 创建并在后台启动所有服务
docker compose ps           # 查看服务状态
docker compose logs -f      # 跟踪所有服务的日志
docker compose logs -f db   # 只查看 db
docker compose stop         # 停止(保留容器)
docker compose start        # 重新启动
docker compose down         # 停止并删除容器和网络(保留 Volume)
docker compose down -v      # 同时删除 Volume(数据会消失!)

修改 compose.yaml 后,再运行一次 docker compose up -d,Compose 只会重建有变化的服务(示例见 docker compose 命令)。

项目名称与文件名

  • 项目名称默认是文件夹名称,也可以在 compose.yaml 最上方指定 name: myproject,或使用 docker compose -p myproject。
  • Compose 默认按顺序查找 compose.yaml、compose.yml、docker-compose.yaml、docker-compose.yml。新项目建议使用 compose.yaml。
  • 文件开头的 version: "3.8" 是旧格式的写法,现在已经不需要了,写了只会出现警告。

下一步

重点回顾

  • compose.yaml 描述多个服务、网络和 Volume,一条命令就能全部启动。
  • Compose 会自动创建项目网络,服务之间通过服务名称连接。
  • docker compose down 会保留 Volume;down -v 会删除数据。
  • Docker Desktop 会将 Compose 项目显示为一组。

动手练习

练习 1:在本章的项目中,用一条命令只查看 db 服务最后 5 行日志。

答案
docker compose logs --tail 5 db

练习 2:运行 docker compose down 后再运行 up -d,Adminer 中创建的数据表还在吗?改用 down -v 呢?

答案

运行 down 后数据还在,因为 pgdata Volume 得到了保留;down -v 会删除 Volume,数据库重新初始化,数据表也就不见了。

常见问题

docker-compose 和 docker compose 有什么不同?

docker-compose(带连字符)是已停止维护的 v1 独立程序;现在使用 Docker CLI 的插件 docker compose(空格),本教程使用 v5。

compose.yaml 和 docker-compose.yml 都可以吗?

都可以,Compose 会按顺序查找。新项目建议使用 compose.yaml。

项目名称是怎么决定的?

默认是 compose.yaml 所在文件夹的名称,容器、网络、Volume 的名称都会加上它作为前缀。可以用 name: 或 -p 指定。

更新于 2026年10月14日