目錄
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:
三個服務:
| 服務 | 作用 |
|---|---|
web | nginx,把 ./site 資料夾當作網站,主機 8080 |
db | PostgreSQL 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網路,三個服務都在裡面,可以用服務名稱互相連線。 pgdataVolume 實際的名稱是compose-demo_pgdata。db沒有設定ports,所以 PORTS 欄位只有5432/tcp,外部連不到它。
打開 http://localhost:8080:

用 Adminer 管理資料庫
打開 http://localhost:8081 是 Adminer 的登入畫面。注意 System 預設是 MySQL:

依照下面的設定登入:
| 欄位 | 填入 |
|---|---|
| System | PostgreSQL(一定要改,否則會用 MySQL 的方式連線而失敗) |
| Server | db(服務名稱,透過 Compose 網路解析) |
| Username | postgres |
| Password | example(compose.yaml 中的 POSTGRES_PASSWORD) |

登入成功後,畫面會顯示 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;

按 Execute,三個指令依序執行,最後的 SELECT 列出剛才新增的資料:

查看日誌
$ 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 語法完整說明:build、ports、volumes、environment、depends_on、healthcheck……
- docker compose 常用指令
- 實戰:用 Compose 架設 WordPress
重點回顧
- 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日