Section 1:痛點 — 「在我電腦上可以跑」的根源
你剛加入一個新專案,同事丟給你一份 README,上面寫著:
# Getting Started
# Prerequisites
- Node.js 18.x(注意:不能用 19 或 20,會有 breaking change)
- PostgreSQL 14(不是 15,因為用了 14 才有的功能)
- Redis 7.0.x
- RabbitMQ 3.11
- Python 3.10(backend 服務用)
- 記得設定 PATH 和 PYTHONPATH…
# Setup
1. 安裝 PostgreSQL,記得建 user 和 database
2. 修改 pg_hba.conf(參考 wiki 第 7 頁)
3. 啟動 Redis,確認 port 6379 沒被占用
4. 設定 RabbitMQ virtual host…
# (以下省略 30 步)
你跟著做,花了一整天。終於,你執行 npm run dev, 報錯。你問同事,同事說:「奇怪,在我電腦上可以跑啊。」
根源很簡單:每個人的電腦環境不同 — 作業系統版本、已安裝的套件版本、環境變數設定、甚至 locale 差異,都可能導致行為不一致。 這不是人的問題,是「把環境配置寫在腦袋裡」這種做法的問題。
類比:工廠的生產線設計圖
Docker Compose 像是工廠的生產線設計圖(YAML 檔)。你把整個工廠需要的機器、原料、電路配置全部寫進這份設計圖裡。 任何人拿到這份設計圖,執行 docker compose up,就能在自己的電腦上蓋出一模一樣的工廠—— 不管他的電腦是 Mac、Windows 還是 Linux。
沒有 Docker Compose
- • 新人 onboarding 花 1–3 天
- • 版本衝突難以追蹤
- • 環境差異導致 bug 難以重現
- • README 永遠過時
- • 「在我電腦上可以跑」
有了 Docker Compose
- • 新人 onboarding:
git clone && docker compose up - • 所有依賴版本鎖死在 YAML
- • 任何環境行為完全一致
- • YAML 就是最新的文件
- • 永遠可以跑
Section 2:Docker Compose 基礎架構
一切從最小可行的 docker-compose.yml 開始。 下面是一個 Web 應用 + 資料庫的基本結構,理解這個就掌握了 80% 的核心概念。
三個核心概念
services — 每個 service 就是一個 Container
services 下的每個鍵(web、db)對應一個 Container。 服務名稱同時也是該 Container 在 Docker 內部網路的 hostname — 所以 web 可以用postgresql://db:5432/myapp 連接到 db, 不需要知道容器的 IP。
build vs image — 自己的服務 vs 第三方
build: . 意思是「用這個目錄的 Dockerfile 自己建立 image」,用於你自己開發的服務。image: postgres:14 意思是「直接從 Docker Hub 拉現成的 image」, 用於 PostgreSQL、Redis、RabbitMQ 等第三方服務,不需要自己寫 Dockerfile。
ports — 「主機:容器」對應格式
"3000:3000" 意思是:把主機的 3000 port 對應到容器的 3000 port。 如果你的主機 3000 port 被占用了,改成 "3001:3000", 用主機 3001 連進去容器的 3000。容器之間互連不需要 ports,只有讓主機(你的瀏覽器)能存取時才需要。
Section 3:完整全端應用範例
實際專案的 Compose 檔通常包含 4 個服務:前端、後端、資料庫、快取。 以下是一個 Next.js + FastAPI + PostgreSQL + Redis 的完整範例,附上每個關鍵設定的說明。
為什麼 backend 用服務名稱 "db" 連資料庫,而不是 "localhost"?
Docker Compose 會自動為所有服務建立一個內部網路(default network)。 在這個網路裡,每個服務的名稱就是它的 hostname。 backend 容器和 db 容器是兩個不同的 Container,各自有獨立的 network namespace, 所以 backend 裡的 localhost 指的是 backend 容器本身,不是 db 容器。 要連到 db 容器,必須用 db(服務名稱)作為 hostname。
Section 4:Volumes — 三種掛載方式
Volumes 是 Docker 中最容易讓初學者搞混的概念。問題的核心是: 容器預設是暫時的(ephemeral) — 容器刪掉,裡面的資料就消失。 Volumes 就是「讓資料在容器生命週期之外存活」的機制。
1Bind Mount — 開發時的即時同步
把本機的目錄「掛進」容器,本機改動的檔案會即時同步到容器裡(反之亦然)。 開發時最常用,讓你不需要重新 build image 就能看到改動效果。
注意:Bind Mount 的路徑是相對於 docker-compose.yml 的位置。./frontend 表示「跟 docker-compose.yml 同層的 frontend 資料夾」。
2Named Volume — 資料持久化
由 Docker 管理的磁碟空間,有自己的名字,不跟特定主機路徑綁定。 最常用於資料庫資料 — 你刪掉 Container,資料還在;下次 docker compose up, 資料庫的資料自動恢復。
3匿名 Volume — 避免主機覆蓋容器
這是最容易被忽略但非常重要的技巧。當你用 Bind Mount 把本機目錄掛進容器時, 本機的node_modules也會被掛進去, 可能蓋掉容器內正確安裝的node_modules。
三種 Volume 對比
| 類型 | 語法 | 用途 | 資料持久 |
|---|---|---|---|
| Bind Mount | ./src:/app/src | 開發時即時同步 | 是(在主機上) |
| Named Volume | pg_data:/var/lib/... | 資料庫持久化 | 是(Docker 管理) |
| 匿名 Volume | /app/node_modules | 避免主機覆蓋容器 | 否(容器刪掉消失) |
Section 5:常用指令速查表
日常開發中你 90% 的時間只會用到下面這些指令。遇到問題時,先看 logs,再進容器除錯。
Compose 指令 vs 單獨 Docker 指令
在有 docker-compose.yml 之前,你需要用 docker run 逐一啟動每個 Container, 還要手動建立網路讓它們互連。Compose 把這些全部自動化了。
沒有 Compose(手動啟動 4 個服務)
docker network create myapp-net
docker run -d --name db \
--network myapp-net \
-e POSTGRES_PASSWORD=secret \
postgres:14
docker run -d --name redis \
--network myapp-net redis:7
docker run -d --name backend \
--network myapp-net \
-e DATABASE_URL=... \
./backend
# ... 繼續
有 Compose(一個指令)
docker compose up -d
# 自動建立 network
# 自動按 depends_on 順序啟動
# 自動設定服務間 hostname
# 自動掛 volumes
Section 6:開發效率最佳實踐
掌握了基礎之後,這三個進階技巧可以讓你的 Docker Compose 工作流程更專業、 更接近生產環境的實際做法。
1Override 檔案:區分開發與生產環境
開發環境需要 Bind Mount(即時同步)、暴露 debug port;生產環境需要 CPU/Memory 限制、 不暴露不必要的 port。用 Override 機制,讓同一套 Compose 設定適應不同環境, 不需要維護兩份完全不同的 YAML。
2健康檢查 + depends_on:確保啟動順序正確
depends_on 預設只等 Container「啟動」,不等服務「就緒」。 PostgreSQL Container 啟動後還需要幾秒初始化資料庫,在這段時間內如果 backend 試圖連線,就會失敗崩潰。 搭配 healthcheck 可以確保「服務真的 ready 了才啟動下一個」。
3開發/生產分離的 Dockerfile
開發 Dockerfile 著重快速迭代(熱重載、dev dependencies 全裝); 生產 Dockerfile 著重體積最小化、安全性(移除 devDependencies、multi-stage build)。 兩者應該分開維護,不要用同一個 Dockerfile 塞一堆條件判斷。
掌握 Compose 之後,下一步可以探索
Container Registry
把 build 好的 image 推到 Docker Hub 或 AWS ECR,讓 CI/CD pipeline 和生產伺服器可以拉取固定版本的 image。
Kubernetes
Compose 適合單機開發環境;Kubernetes 是 Compose 的「生產等級進化版」,支援多節點、自動擴縮容、滾動更新。
Docker Swarm
Docker 官方的叢集管理工具,比 Kubernetes 簡單,適合中小型團隊從 Compose 升級到多機部署的過渡方案。