哈囉,大家好!歡迎來到我們 Docker 基礎篇的最終章!
在昨天的練習中,我們已經學會了用 Dockerfile
打包單一應用,並用 docker run
啟動它。但這就像是學會了單兵作戰,在真實的專案戰場上,我們面對的往往是需要多兵種協同作戰的複雜情境。
幾乎沒有一個現代應用是單一服務。以我們公司的 OTA (Over-the-Air) 專案為例,一個最基本的開發環境,就至少包含三個核心服務:
如果堅持使用 docker run
,我們需要下達三次冗長的指令、手動建立網路來讓它們溝通、透過複雜的參數設定環境變數、還要人工確保資料庫必須比後端先啟動... 這完全不切實際,且難以與團隊成員共享。
所以使用 Docker Compose 的好處就來了!
compose.yaml
Docker Compose 的核心,就是一份名為 compose.yaml
(或 docker-compose.yml
) 的設定檔。這份檔案,就是我們整個應用程式的「部署藍圖」。
官方文件是這樣定義的:
Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services.
(Compose 是一個用於定義和運行多容器 Docker 應用的工具。透過 Compose,您可以使用一個 YAML 檔案來配置您應用的服務。)
以下是一個根據 OTA 專案簡化過的 compose.yaml
,讓我們來逐一解構它:
# compose.yaml
# 定義 Compose 檔案的版本,建議使用 '3.8' 或更新
version: '3.8'
# 這裡是所有服務的定義區
services:
# 1. 資料庫服務
ota-mariadb:
image: mariadb:10.11
environment:
MYSQL_ROOT_PASSWORD: example_password
MYSQL_DATABASE: ota_service
MYSQL_USER: ota_user
MYSQL_PASSWORD: ota_password
ports:
- "3306:3306"
volumes:
- ./data/ota-mariadb:/var/lib/mysql
networks:
- ota-network
ota-mariadb
服務:
image: mariadb:10.11
:直接從 Docker Hub 拉取現成的 MariaDB 映像檔。environment
:設定環境變數,用來初始化資料庫的密碼、使用者等。ports: - "3306:3306"
:將我們本機的 3306 埠,映射到容器的 3306 埠,方便我們從本機連線資料庫。volumes
:使用 Bind Mount 將本機的 ./data/ota-mariadb
目錄掛載到容器內,實現資料持久化。# 2. 後端服務
ota-backend:
build: ./backend
environment:
- DB_HOST=ota-mariadb # 關鍵!直接使用服務名稱作為主機
- DB_PORT=3306
- DB_USER=ota_user
- DB_PASSWORD=ota_password
- DB_NAME=ota_service
- SERVER_PORT=8080
ports:
- "8080:8080"
depends_on:
- ota-mariadb # 確保資料庫先啟動
networks:
- ota-network
ota-backend
服務:
build: ./backend
:告知 Compose,這個服務的 Image 需要透過 ./backend
目錄下的 Dockerfile
來建置。environment: - DB_HOST=ota-mariadb
:這是 Compose 最神奇的地方! 在同一個 ota-network
網路中,容器之間可以直接使用服務名稱作為主機名 (hostname) 來互相通訊。Compose 內建了 DNS 解析!depends_on: - ota-mariadb
:明確定義了啟動順序,Compose 會確保 ota-mariadb
容器啟動完成後,才啟動 ota-backend
。 # 3. 前端服務
ota-frontend:
build: ./frontend
environment:
- VITE_API_BASE_URL=http://localhost:8080
ports:
- "80:80"
depends_on:
- ota-backend
networks:
- ota-network
ota-frontend
服務:
build
來建置前端 Image。VITE_API_BASE_URL
告訴前端應用,後端 API 的位址在 http://localhost:8080
。# 4. 網路定義
networks:
ota-network:
driver: bridge
networks
定義:
ota-network
的自訂橋接網路,並將所有三個服務都加入這個網路,確保它們可以互相通訊,同時又與外部網路環境隔離。有了這份藍圖,啟動整個專案環境,從原本繁瑣的多個步驟,簡化為一個指令。
打開終端機,確定你在 compose.yaml
所在的專案根目錄,然後執行:
# -d 參數代表 detached,讓容器在背景運行
docker compose up -d
Compose 會自動幫你完成所有事:
ota-network
的專屬網路。depends_on
的順序,首先啟動 ota-mariadb
。./backend
的 Image (如果不存在),並啟動 ota-backend
容器。./frontend
的 Image,並啟動 ota-frontend
容器。ota-network
,讓它們可以互相溝通。http://localhost
(因為我們映射到 80 埠)。http://localhost:8080/health
(假設有健康檢查路由)。localhost:3306
。三個服務會完美地協同工作,一個完整的開發環境就這樣輕鬆地運行起來了。
當開發工作結束,或想重置環境時,只需要一個指令:
docker compose down
Compose 會聰明地找到由這份 compose.yaml
啟動的所有資源,並將它們停止、移除。
小知識:預設情況下,docker compose down 不會刪除 Volume。如果您想連同 Volume 一起徹底清除(例如 pg-data 如果是用 Volume 的話),需要加上 --volumes 旗標:docker compose down --volumes。
從這個真實的專案例子中,我們了解到 Docker Compose 的價值:
up
和 down
兩個指令,就涵蓋了 90% 的日常操作。compose.yaml
,就能快速重現出完全相同的開發環境。然而,Docker Compose 擅長的是單一主機上的編排。當我們需要將應用部署到數十、數百台伺服器上,追求極致的穩定性、實現自動擴展與故障自我修復時,我們就需要一位更強大的「容器編排平台」。
在我們系列文章的下一階段,我們就要正式介紹 —— Kubernetes!明天見!