在容器化技術已成為軟體開發與部署標準的一個時代,您可以使用 Docker Compose 作為一種“多容器協同管理”方案,已被廣泛應用於快速啟動開發環境、測試環境以及在生產環境中協同多服務的部署。
本文將帶領大家深入探討 Docker Compose,並提供詳細的說明與範例。文章不僅涵蓋了安裝與基本用法,也納入進階應用情境,如整合資料庫、前後端服務,以及常見的資料分析工具與監控平台(例:Metabase、Prometheus、Grafana、ELK 堆疊等)。
Docker Compose 緣起與基本概念
多容器協同的動機
一般而言,使用 Dockerfile 可以為單一應用或服務建立容器映像。但是,現代應用程式通常牽涉到多個服務。例如,一個典型的微服務架構可能需要:
- 前端(如:Node.js、Ruby on Rails、Flask 或 React SPA)
- 後端(如:Java、Go、Python…)
- 資料庫(MySQL、Postgres、MongoDB…)
- 缓存與排程工具(Redis、RabbitMQ、Kafka…)
- 其他支援服務(Nginx、HAProxy、ElasticSearch…)
如果使用單純的 docker run,啟動每個服務的容器都需要一長串命令,且還得手動指定網路連線、port 映射以及環境變數。當服務越來越多時,就產生了巨大的維護成本。為了解決這個問題,Docker 官方團隊推出了 Docker Compose 來將多容器的架構“一次性”定義和運行。
Docker Compose 與 Dockerfile 的差異
- Dockerfile:用於定義單個容器映像,描述了該映像如何被建置(如:從哪個 Base Image、安裝哪些套件、執行哪些指令)。
- Docker Compose:用於定義應用程式及多容器之間的協同關係。它透過 docker-compose.yml(或 docker-compose.yaml)這種 YAML 配置檔,將多個容器整合在一個“專案(Project)”中管理,可以一次啟動、一次停止、多容器一起重新部署,也可以明確定義容器間的網路、卷(volumes)以及其他設定。
Docker Compose 架構與 V1、V2 版本沿革
Docker Compose 在早期名為 Fig,後來被 Docker 收購並重新命名。隨著時間演進,從 V1(基於 Python)到現今流行的 V2(Go 語言,與 Docker CLI 更緊密整合),官方也逐步淘汰舊版 Compose。
在 Docker Desktop 內常可看到指令 docker compose(中間有空格)即代表新版 V2,而舊版則多是 docker-compose(中間無空格,獨立二進位檔)。從 2023 年中開始,舊版 V1 逐漸被淘汰,建議使用者都升級至 Docker Compose V2,以便獲得最新功能與支援。
Docker Compose 安裝
在 Linux 上安裝
如果您使用的是 Linux 環境(如 Ubuntu、Debian、CentOS 或 Fedora),可以透過套件管理器或是直接從官方 GitHub 釋出的二進位檔來進行安裝。使用以下方式來完成安裝:
- 下載 Docker Compose V2 二進位檔
sudo curl -L "https://github.com/docker/compose/releases/download/v2.17.2/docker-compose-$(uname -s)-$(uname -m)" \ -o /usr/local/bin/docker-compose
- 賦予可執行權限
sudo chmod +x /usr/local/bin/docker-compose
- 建立系統連結(可選)
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
- 確認安裝
docker-compose version
或
docker compose version
視版本而定。若顯示正確版本資訊則代表安裝成功。
注意:部分新版 Linux 發行版或 Docker Engine 可能預設已支援 docker compose(V2),可以先嘗試 docker compose version 看看是否已就緒。若非必要也可不使用舊版 docker-compose 二進位。
在 macOS 與 Windows 上使用 Docker Desktop
對於 macOS 和 Windows 用戶來說,安裝 Docker Desktop 後通常會自動附帶最新版本的 Docker Compose(V2)。您可以直接在終端機(macOS)或 PowerShell / Command Prompt(Windows)輸入:
docker compose version
若有正確回應,即可使用最新版的 Compose 功能。
安裝驗證
完成後,可輸入下列的命令確保指令可以正常運行:
docker compose version
若成功顯示類似 Docker Compose version v2.17.x 等字樣,就代表安裝完成。
Docker Compose 核心概念與 YAML 配置檔
Docker Compose 的三個核心物件:Project、Service、Container
- Project:整個 Compose 專案(即一個 docker-compose.yml 檔案)可視為一個專案,包含了多個服務的定義。
- Service:服務層級的概念,用於描述將要運行的容器。“web”、“db”、“redis” 等皆是服務名稱的命名。
- Container:當執行 docker compose up 後,就會產生對應的容器。
docker-compose.yml 常見參數總覽
version: '3.8'
services:
# 舉例:web 服務
web:
build: .
image: my-web
container_name: my-web-app
ports:
- "8080:80"
environment:
- NODE_ENV=development
volumes:
- ./src:/var/www/html
networks:
- my-network
depends_on:
- db
command: ["npm", "start"]
restart: always
# 舉例:db 服務
db:
image: mysql:5.7
container_name: my-db
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: testdb
volumes:
- db_data:/var/lib/mysql
networks:
- my-network
networks:
my-network:
driver: bridge
volumes:
db_data:
- version:指定 compose 的版本(建議使用 3.8 或更高)。
- services:主要定義容器服務。
- image:指定要使用的映像名稱(可來自 Docker Hub 或自訂鏡像)。
- build:如果要從 Dockerfile 建置映像,可使用此參數提供建置內容,如 build: .(在目前目錄尋找 Dockerfile)。
- container_name:自訂容器名稱(可省略,由 Compose 自動產生)。
- ports:定義主機與容器的埠對應,例如 8080:80 代表本機 8080 對應容器 80。
- volumes:掛載卷或本地資料夾至容器內。
- environment:設定環境變數,可使用字串或陣列方式。
- networks:定義該服務所連接到的網路。
- depends_on:指定服務依賴關係(如 web 需要先啟動 db)。
- command:覆蓋容器預設的執行命令。
- restart:重啟策略(如 always、on-failure、unless-stopped)。
- networks:定義與容器要使用的網路模式,可以是 bridge、host 或自訂 driver。
- volumes:定義資料卷,存放宿主機與容器中的持久性資料。
環境變數與 env_file
若要在外部定義環境變數,可使用 .env 這類設定檔案,或在 docker-compose.yml 中引用 env_file:
version: "3.8"
services:
web:
image: node:14
env_file:
- .env
# 省略其他...
在 .env 檔中可寫:
NODE_ENV=production
API_KEY=123456
Compose 啟動時就會自動將此 .env 內容帶入容器。
使用 Build 架設自訂映像
若您要在本地自行建置映像,可在 docker-compose.yml 內使用 build:
version: '3'
services:
myapp:
build:
context: ./myapp
dockerfile: Dockerfile
ports:
- "3000:3000"
執行:
docker compose build
docker compose up -d
即可由該目錄下的 Dockerfile 建置出對應映像後並啟動容器。
Volumes 與檔案系統掛載
多數時候服務需要持久化存儲,或需要掛載程式碼目錄。Compose 支援多種卷掛載方式:
- Anonymous Volume:不命名,通常用於暫存。
- Named Volume:可在最底部 volumes 區域命名,如 db_data,利於持久化管理。
- Host Path:直接掛載主機本地路徑,如 ./src:/app/src,適合開發模式。
範例:
services:
db:
image: postgres
volumes:
- db-volume:/var/lib/postgresql/data
volumes:
db-volume:
或以 Host Path:
services:
web:
image: php:8-apache
volumes:
- ./webdata:/var/www/html
Networks 與容器間的網路連線
Compose 會自動為同一個 docker-compose.yml 中的服務容器建立預設網路,並透過服務名稱(如 db, web)來互相 DNS 解析,同時對應端口。如果要自訂網路:
networks:
my-network:
driver: bridge
然後在服務區塊:
services:
web:
networks:
- my-network
db:
networks:
- my-network
如此 web 容器可用 db:3306(取決於服務內部對外開放的埠)來連接資料庫。
如何使用範例:Node.js + MongoDB
假設我們有一個專案需要使用 Node.js 做後端,並使用 MongoDB 做數據庫。我們希望只要執行一個命令就能同時啟動 Node.js 與 MongoDB。以下舉例說明。
撰寫 docker-compose.yml
假設我們在專案根目錄下建立一個 docker-compose.yml 檔案,內容如下:
version: "3.8"
services:
app:
image: node:18-alpine
container_name: node_app
working_dir: /app
volumes:
- ./:/app
command: sh -c "npm install && npm run start"
ports:
- "3000:3000"
depends_on:
- mongo
networks:
- app_network
mongo:
image: mongo:6.0
container_name: mongo_db
restart: always
ports:
- "27017:27017"
volumes:
- mongodata:/data/db
networks:
- app_network
networks:
app_network:
driver: bridge
volumes:
mongodata:
說明:
- app 服務為一個 Node.js 容器,直接使用 node:18-alpine 作基底映像。
- 使用 volumes 將本地整個專案掛載到容器 /app 資料夾。
- command: sh -c “npm install && npm run start” 表示啟動容器前會自動安裝依賴套件,再執行 npm run start。
- ports: “3000:3000″,將容器內的 3000 port 對外映射到本機的 3000 port。
- depends_on: [mongo] 表示啟動 app 前,會先啟動 mongo。
- mongo 服務使用官方 mongo:6.0 映像,並指定資料卷 mongodata,以保證資料庫持久化。
- 建立一個自訂 app_network 的 bridge 型網路,讓 app 與 mongo 互通。
執行範例與測試
- 執行 docker compose build(若有 build 指令)
如果使用既有映像就不用 build;本範例直接拉取 node 與 mongo,所以可省略 build。 - 執行 docker compose up
docker compose up -d
系統會同時拉取 node:18-alpine 與 mongo:6.0 映像,並建立兩個容器:
- node_app
- mongo_db
- 檢查運行狀態
docker compose ps
若顯示兩個服務皆為 Up 狀態,即表示成功。
- 測試應用
如果您的 Node.js 應用監聽在 3000 port,可打開瀏覽器輸入 http://localhost:3000 驗證是否正常顯示。
查看資料庫與容器狀態
- 若要查看容器日誌:
docker compose logs -f mongo
- 若要連線 Mongo 容器,可:
docker exec -it mongo_db bash
進入容器後,可使用 mongosh 連接本地執行查詢。
進階應用:多容器案例與整合示例
以下將列舉更多常見的多容器整合場景,包括 CMS、BI 工具、監控平台,以及大數據相關等。
WordPress + MariaDB
情境:在本地或伺服器上想快速啟動一個 WordPress + MariaDB 的環境,並能保留資料。
version: '3.8'
services:
db:
image: mariadb:10.6
container_name: my_mariadb
environment:
MYSQL_ROOT_PASSWORD: "rootpass"
MYSQL_DATABASE: "wordpress"
MYSQL_USER: "wp_user"
MYSQL_PASSWORD: "wp_pass"
volumes:
- db_data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- wp-net
wordpress:
image: wordpress:latest
container_name: my_wordpress
depends_on:
- db
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: "wp_user"
WORDPRESS_DB_PASSWORD: "wp_pass"
WORDPRESS_DB_NAME: "wordpress"
ports:
- "8080:80"
volumes:
- wp_html:/var/www/html
networks:
- wp-net
networks:
wp-net:
volumes:
db_data:
wp_html:
- 透過 depends_on 確保 MariaDB 容器先啟動。
- WordPress 中 WORDPRESS_DB_HOST 需使用 db 服務名稱,以容器內 DNS 方式連線。
- 所有資料均掛載到名為 db_data 與 wp_html 的 volume。
Metabase + MS SQL Server
情境:需要搭建簡單 BI(商業智慧)分析環境,Metabase 連到 SQL Server 做分析與可視化。
- SQL Server 容器:
version: '3.8' services: sqlserver: image: mcr.microsoft.com/mssql/server:2022-latest container_name: sqlserver environment: ACCEPT_EULA: "Y" MSSQL_SA_PASSWORD: "yourStrongPassword!" ports: - "1433:1433" volumes: - ./mssql_data:/var/opt/mssql networks: - analysis-net networks: analysis-net:
- Metabase 容器(可加入在同一份 compose 檔):
metabase: image: metabase/metabase:latest container_name: metabase ports: - "3000:3000" networks: - analysis-net
- 將 Metabase 與 sqlserver 都連到 analysis-net,可直接使用 sqlserver:1433 連線資料庫。
- 啟動後打開瀏覽器到 http://localhost:3000,並透過設定檔案或 UI 介面設定資料庫來源。
Prometheus + Grafana
情境:監控 Docker 容器指標,或其他服務的效能指標。
- Prometheus:
- 負責資料收集(scrape metrics),常使用 prometheus.yml 作為配置。
- Grafana:
- 數據可視化 UI。
簡易 docker-compose.yml 範例(yaml配置實例):
version: '3.8'
services:
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
networks:
- monitor-net
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
networks:
- monitor-net
depends_on:
- prometheus
networks:
monitor-net:
將 Prometheus 配置檔(prometheus.yml)放在同目錄下,指明要抓取哪些容器或服務指標。
ELK 堆疊 (Elasticsearch、Logstash、Kibana)
情境:建立日誌分析平台。
version: '3.8'
services:
elasticsearch:
image: elasticsearch:8.5.0
container_name: es
environment:
- discovery.type=single-node
ports:
- "9200:9200"
networks:
- elk-net
logstash:
image: logstash:8.5.0
container_name: ls
networks:
- elk-net
depends_on:
- elasticsearch
ports:
- "9600:9600"
kibana:
image: kibana:8.5.0
container_name: kb
depends_on:
- elasticsearch
ports:
- "5601:5601"
networks:
- elk-net
networks:
elk-net:
- elasticsearch、logstash、kibana 三者彼此連通即可形成 ELK 堆疊。
- 連線方式:Kibana 預設 http://localhost:5601,Elasticsearch 預設 http://localhost:9200。
常用 Docker Compose 命令與操作表格
下表彙整了使用 Docker Compose(V2 語法)的常見操作命令與對應用途(你也可參考官方的文件):
命令 | 用途 | 範例 |
---|---|---|
docker compose up [-d] | 啟動所有在 docker-compose.yml 裡定義的服務;-d 表示後台執行 | docker compose up -d |
docker compose down | 停止並刪除所有容器、網路(默認創建)、但不刪除 volume 與 image | docker compose down |
docker compose build | 根據 docker-compose.yml 中的 build 配置建置映像 | docker compose build |
docker compose start | 啟動已建立但目前停止的容器 | docker compose start |
docker compose stop | 停止已運行的容器,但不刪除容器 | docker compose stop |
docker compose restart | 重啟容器 | docker compose restart web |
docker compose ps | 列出 Compose 專案相關的容器、狀態、Port 映射 | docker compose ps |
docker compose logs [-f] [service] | 查看容器日誌;-f 持續關注;可指定特定服務 | docker compose logs -f web |
docker compose pull | 從遠端倉庫拉取所有服務定義的映像 | docker compose pull |
docker compose rm | 刪除已停止的容器 | docker compose rm |
docker compose exec <service> bash | 進入某個容器進行操作(類似 docker exec -it) | docker compose exec db bash |
docker compose port <service> <port> | 查詢服務容器內部埠對應宿主機的埠映射 | docker compose port web 3000 |
docker compose version | 顯示 Compose 版本資訊 | docker compose version |
常見問題 (FAQ)
為何要使用 Docker Compose 而非手動 docker run?
當只有一個容器時,手動 docker run 當然夠用。然而實際應用幾乎都需要多容器(前端、後端、DB…),若每次都要手動串接大量參數,維護成本高、錯誤率也高。Docker Compose 提供了易讀的 YAML 檔集中管理,可一次執行 docker compose up -d 就啟動所有容器,非常方便。
Docker Compose V1 與 V2 差別是什麼?
- V1 以 docker-compose (中間無空格)單一二進位檔執行,基於 Python。
- V2 則是透過 docker compose 子指令整合到 Docker CLI 中,更符合新一代 Docker 環境。官方已於 2023 年起逐漸淘汰 V1,建議使用 V2。
可以在生產環境使用 Docker Compose 嗎?
Compose 主要用於「單台伺服器的多容器協同」。若在生產環境只有單台機器,Compose 當然可以快速部署。但若是要建立大型叢集或做更進階的自動擴展、滾動更新,建議使用 Kubernetes 或 Docker Swarm 等分散式容器管理平台。Compose 的 deploy 區段在 swarm mode 下也能派上用場,但普遍還是 K8s 在生產環境更常見。
depends_on 能否保證服務已就緒後才啟動?
depends_on 只會保證容器按順序啟動,但不保證容器中服務真正啟動完成。若需要確保 DB 真的能連接,建議搭配健康檢查(healthcheck)或像 wait-for-it.sh 或 wait-service 之類的機制。
資料卷 (Volumes) 該如何備份與清理?
- Docker Compose 使用到的 Volume 在默認情況下會保留,即使容器已刪除。清理時可用 docker volume rm <volume>。
- 備份可透過 docker run –rm -v my_volume:/data -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data 等方式。
如何在同一台主機上同時執行多個 docker-compose.yml?
只要確保不同 Compose 專案的容器名稱、網路名稱、port 映射等不衝突即可。例如可在不同目錄下建立 docker-compose.yml 檔並執行。如果擔心名稱衝突,可使用 -p 或 –project-name 參數自訂專案名稱。
如何自動重啟容器?
在 docker-compose.yml 裡的每個服務段落可加上 restart: always 或 restart: on-failure 等策略。如果遇到容器崩潰,可自動重啟。
是否能在 Docker Compose 中整合 secrets 來管理敏感資訊?
在 Compose v3.1+ 開始提供 secrets 機制,類似 Docker Swarm。可透過 secrets: 配置機制將機密資料加載到容器內。也可用 environment variable 的方式,但不建議直接將密碼硬編碼在檔案中,可搭配 .env 檔或 CI/CD 管理。
當前使用 Docker Compose 的 YAML 檔已經很複雜時如何維護?
- 可以使用多個 YAML 檔,透過 docker compose -f base.yml -f override.yml up -d 來做環境差異的覆蓋。例如分為 docker-compose.yml(預設) 與 docker-compose.override.yml(開發或測試設定)。
- 也可以使用 anchor & alias 的 YAML 語法來減少重複定義。
總結
Docker Compose 是一個能大幅簡化多容器部署流程的工具,不論在開發、測試或小型生產環境,都能極大提升維運效率與環境一致性。
總體而言,Docker Compose 不僅能在開發測試階段提高效率與可重現性,也能透過 docker compose 指令組合在小型生產部署中提供多容器協同運行的便利。希望本文從入門到進階的範例,能協助您更熟練掌握 Compose 的各種技巧與應用情境。
資料來源
- Docker Compose | 菜鸟教程
- 使用 Docker Compose 摻在一起做懶人包 – iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天
- Docker Compose 的基本使用方式 | MagicLen