如果把 Docker Container 比喻為「樂器」,那麼 Docker Compose 就是「樂團指揮」。
- 沒有 Docker Compose 時:如果你的網站需要網頁伺服器(如 Nginx)、後端程式(如 Node.js/Python)跟資料庫(如 MySQL),你必須手動敲好幾行又長又複雜的
docker run指令,還要手動幫它們建立網路、掛載資料夾。 - 有了 Docker Compose 後:你只需要寫一份名為
docker-compose.yml的設定檔,把所有容器的規格寫清楚,接著只需要執行 一行指令,就能同時啟動或關閉所有服務!
核心概念:一個檔案、兩個指令
學習 Docker Compose,只要掌握以下核心架構:
docker-compose.yml設定檔:用 YAML 格式編寫,用來定義有哪些容器(Services)、網路(Networks)與資料卷(Volumes)。docker compose up:一鍵打包啟動所有容器。docker compose down:一鍵停止並清除所有容器。
快速實戰:建立第一個 Compose 專案
以下建立一個極簡的範例:用 Docker Compose 一起啟動 Nginx 網頁伺服器 與 Redis 快取資料庫。
第一步:建立專案資料夾
在終端機(Terminal)或 Command Prompt 建立一個新資料夾並進入:
mkdir my-compose-demo
cd my-compose-demo
第二步:建立 docker-compose.yml
在該資料夾內建立一個名為 docker-compose.yml 的檔案,貼入以下內容:
version: '3.8'
services:
webserver:
image: nginx:alpine
container_name: my-web-server
ports:
- "8080:80"
restart: always
cache:
image: redis:alpine
container_name: my-redis-cache
restart: always
關鍵欄位解析:
version:定義 Docker Compose 的語法版本(一般維持'3.8'即可)。services:底下定義你要啟動的各個容器。- webserver: 服務 1:網頁伺服器
- cache:服務 2:Redis 資料庫
image:指定使用的 Docker Image 映像檔名稱(這裡選用輕量化的alpine版本)。ports:連接埠對映,格式為"主機 Port : 容器內 Port"。這裡代表存取電腦的8080Port 會對應到 Nginx 的80Port。restart: always:設定當容器意外崩潰時會自動重啟。
第三步:啟動服務
在 docker-compose.yml 所在的資料夾中,執行以下指令:
docker compose up -d
小技巧:
-d代表在背景執行(Detached mode),這樣終端機就不會被 Log 訊息佔用。
打開瀏覽器輸入 http://localhost:8080,如果你看到 Nginx 的 “Welcome to nginx!” 畫面,就代表服務成功啟動了!
常用指令
學會這幾行指令,就能應付 90% 的日常操作:
1.背景啟動所有服務:docker compose up -d。
根據 docker-compose.yml 的設定,下載映像檔並在背景啟動所有容器。
2.查看運作中的服務:docker compose ps。
列出目前由 Compose 管理的所有容器狀態、埠號對映與運作情形。
3.即時查看容器 Log:docker compose logs -f。
持續印出所有容器的日誌紀錄。若只想看單一服務,可在後方指定名稱,例如 docker compose logs -f webserver。
4.停止並刪除容器:docker compose down。
安全停止所有容器,並釋放它們所佔用的網路環境。
注意事項
1. YAML 縮排格式要求極為嚴格
YAML 檔案嚴禁使用 Tab 鍵,只能使用**空白鍵(Space)**進行縮排!如果不小心混用,Docker Compose 讀取時會直接報錯。
2. 容器間的通訊極度簡單
在同一份
docker-compose.yml底下的容器,預設會自動連到同一個虛擬網路中。重點: 容器之間要互相連線時,主機名稱直接寫「服務名稱(Service Name)」即可!例如後端程式要連 Redis,連線地址直接填
cache:6379,不需要寫 IP。
3. 資料持久化(Volumes)
預設情況下,當容器被
docker compose down刪除時,容器裡產生的新資料也會跟著消失。如果需要保留資料(如資料庫檔案),記得加上volumes設定將資料對映回實體電腦中。
常用關鍵屬性語法解析
在寫 docker-compose.yml 時,你會經常看到以下 10 個核心屬性:
1. environment (環境變數)
用來注入變數到容器內,常見於設定資料庫帳密、系統時區或 API 金鑰。
environment:
POSTGRES_USER: root
POSTGRES_PASSWORD: mysecretpassword
2. volumes (資料持久化與目錄對映)
容器刪除後內部的資料也會跟著消失。volumes 能把主機(Host)的資料夾對映進容器內,確保資料保留下來或用來同步程式碼。
以下是將主機當前的html 對映到容器內/usr/share/nginx/html
volumes:
- ./html:/usr/share/nginx/html
3. build (自訂 Image 編譯)
當官方沒有現成的映像檔,需要透過本地的 Dockerfile 自己建立 Image 時使用。
以下用 . 表示 Dockerfile 在當前所在目錄路徑
build: .
4. depends_on (啟動順序控制)
指定容器間的啟動順序。以下表示必須先啟動db資料庫,才能啟動該服務。
depends_on:
- db
5. network_mode (網路模式)
改變容器的網路連接架構。常見的值有 bridge(預設虛擬網路)與 host(直接共用主機網路)。
network_mode: "host"
6. dns (自訂 DNS 伺服器)
指定容器內部的 DNS 解析伺服器。若預設 DNS 無法解析外網,可自訂 Google (8.8.8.8) 或 Cloudflare (1.1.1.1)。
dns:
- 8.8.8.8
7. cap_add (新增 Linux 系統權限)
Docker 預設會封鎖許多敏感的權限,透過 cap_add 可以精準解鎖特定系統權限(例如網路封包修改)。 以下是開發與營運中最常看到的幾個選項:
| 選項名稱 | 允許容器做的事 | 常見使用情境 |
NET_ADMIN | 修改網路介面、防火牆規則(iptables)、路由表 | VPN 用戶端/伺服器、流量監控工具 |
NET_RAW | 發送原始封包(Raw Sockets) | 在容器內執行 ping 指令、Wireshark 抓包 |
SYS_PTRACE | 追蹤與偵錯其他程序(Process) | 使用 gdb 除錯、效能分析工具(如 strace) |
SYS_TIME | 修改系統的時鐘與時間 | NTP 時間同步服務 |
SYS_ADMIN | 執行各種系統管理操作(接近半個 root) | 掛載檔案系統(mount)、容器內執行 FUSE 檔案系統 |
DAC_READ_SEARCH | 繞過檔案權限檢查直接讀取所有檔案 | 檔案備份工具、系統安全掃描器 |
cap_add:
- NET_ADMIN
8. privileged (最高特權模式)
將容器賦予接近實體主機 Root 的最高權限。常用於 Docker-in-Docker 或存取實體硬體設備
privileged: true
注意事項:開啟
privileged: true會大幅增加容器逃逸的風險,非特殊需求切勿在生產環境開啟!
9. entrypoint (覆蓋預設啟動指令)
強制覆蓋容器啟動時要執行的第一個核心指令。
entrypoint: ["python", "app.py"]
10. sysctls (修改 Linux 核心參數)
用來調整容器內部的 Linux Kernel 參數,常見於高併發效能調優。以下主要提高最大網路連線佇列數
sysctls:
net.core.somaxconn: 1024
實戰範例:完整 docker-compose.yml
我們將上述 10 個屬性整合進一個包含 Python Web、Redis Cache與 Network Agent 的架構中:
version: '3.8'
services:
# 1. Python Web
web:
build: .
container_name: my-web-app
ports:
- "5000:5000"
environment:
- PORT=5000
- REDIS_HOST=cache
volumes:
- .:/app
depends_on:
- cache
entrypoint: ["python", "app.py"]
sysctls:
net.core.somaxconn: 1024
# 2. Redis Cache
cache:
image: redis:7-alpine
container_name: my-redis
dns:
- 8.8.8.8
- 1.1.1.1
# 3. Network Agent
net-tools:
image: alpine
container_name: my-net-tools
network_mode: "host"
cap_add:
- NET_ADMIN
# privileged: true
command: sleep infinity