之前用Docker部署一個Spring Boot+MySQL的應用時,每次啓動都要手動創建網絡、啓動數據庫容器、再啓動應用容器,還得記一堆命令參數。換成Docker Compose後,一個docker-compose up命令就能搞定所有容器的啓動,網絡配置也自動完成,省去了不少麻煩。
Docker Compose是多容器應用編排的利器,尤其適合開發和測試環境。它通過一個YAML文件定義所有服務,實現容器的統一啓停、網絡配置和依賴管理。本文結合實際場景,講解Compose的進階用法,包括網絡隔離、依賴控制、環境變量管理和容器擴展,幫你搞定複雜應用的部署。
一、多容器編排基礎:一個完整的Web應用示例
先看一個典型的多容器應用場景:Spring Boot後端 + MySQL數據庫 + Nginx前端。用Compose編排的docker-compose.yml文件如下:
version: '3.8' # Compose文件版本
services:
# MySQL數據庫服務
mysql:
image: mysql:8.0
container_name: app-mysql
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: appdb
MYSQL_USER: appuser
MYSQL_PASSWORD: apppass
volumes:
- mysql-data:/var/lib/mysql # 數據持久化
ports:
- "3306:3306"
restart: unless-stopped # 容器退出時自動重啓(除非手動停止)
# Spring Boot後端服務
backend:
build: ./backend # 從當前目錄的backend文件夾構建鏡像
container_name: app-backend
depends_on:
- mysql # 依賴mysql服務,確保mysql先啓動
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/appdb
SPRING_DATASOURCE_USERNAME: appuser
SPRING_DATASOURCE_PASSWORD: apppass
ports:
- "8080:8080"
restart: unless-stopped
# Nginx前端服務
frontend:
image: nginx:alpine
container_name: app-frontend
volumes:
- ./frontend:/usr/share/nginx/html # 掛載前端靜態文件
- ./nginx.conf:/etc/nginx/conf.d/default.conf # 掛載Nginx配置
ports:
- "80:80"
depends_on:
- backend # 依賴後端服務
restart: unless-stopped
volumes:
mysql-data: # 聲明數據卷,用於持久化MySQL數據
這個配置實現了三個服務的協同工作:
mysql服務提供數據庫,數據保存在命名卷mysql-data中,避免容器刪除後數據丟失;backend服務依賴mysql,確保數據庫就緒後再啓動;frontend服務通過Nginx提供靜態頁面,反向代理後端接口。
啓動命令:
docker-compose up -d # -d表示後台運行
停止並刪除容器:
docker-compose down # 僅停止容器
docker-compose down -v # 停止容器並刪除數據卷(謹慎使用,會丟失數據)
二、網絡配置:容器間通信與隔離
默認情況下,Compose會為應用創建一個默認網絡,所有服務都在這個網絡中,可通過服務名互相訪問(如backend服務能通過mysql:3306訪問數據庫)。但實際開發中,可能需要更精細的網絡控制。
1. 自定義網絡實現隔離
比如將數據庫網絡和前端網絡隔離,只允許後端訪問數據庫:
version: '3.8'
services:
mysql:
image: mysql:8.0
# 只加入backend-net網絡
networks:
- backend-net
# ...其他配置省略
backend:
build: ./backend
# 同時加入backend-net和frontend-net
networks:
- backend-net
- frontend-net
# ...其他配置省略
frontend:
image: nginx:alpine
# 只加入frontend-net網絡
networks:
- frontend-net
# ...其他配置省略
# 定義兩個自定義網絡
networks:
backend-net: # 後端與數據庫的網絡
driver: bridge
frontend-net: # 前端與後端的網絡
driver: bridge
這樣配置後:
mysql只能被backend訪問(同處backend-net);frontend只能訪問backend(同處frontend-net),無法直接訪問mysql,增強了安全性。
2. 訪問宿主機服務
容器需要訪問宿主機上的服務(如本地開發的API)時,可通過特殊域名host.docker.internal(Windows和Mac)或宿主機IP:
services:
backend:
environment:
# 訪問宿主機的9000端口服務
EXTERNAL_API_URL: http://host.docker.internal:9000
Linux系統需手動指定宿主機IP(如192.168.1.100),或在啓動時添加--add-host=host.docker.internal:host-gateway參數。
三、環境變量與配置管理
硬編碼配置到docker-compose.yml中不利於多環境部署,可通過環境變量文件和動態注入解決。
1. 使用.env文件管理環境變量
創建.env文件存儲環境變量:
# .env文件
MYSQL_ROOT_PASSWORD=root123
MYSQL_DATABASE=appdb
SPRING_PROFILES_ACTIVE=dev
在docker-compose.yml中引用:
services:
mysql:
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} # 引用.env中的變量
MYSQL_DATABASE: ${MYSQL_DATABASE}
backend:
environment:
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE}
2. 不同環境使用不同配置文件
為開發、測試、生產環境創建不同的配置文件:
docker-compose.dev.yml(開發環境)docker-compose.prod.yml(生產環境)
啓動時指定配置文件:
# 開發環境:默認配置 + 開發環境配置
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d
# 生產環境:默認配置 + 生產環境配置
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
生產環境配置示例(docker-compose.prod.yml):
version: '3.8'
services:
backend:
environment:
SPRING_PROFILES_ACTIVE: prod # 覆蓋默認的dev環境
restart: always # 總是自動重啓(生產環境更嚴格)
mysql:
ports:
- "3307:3306" # 生產環境使用不同端口避免衝突
四、依賴控制與健康檢查
depends_on只能保證容器啓動順序,不能確保服務就緒(如數據庫啓動但未完成初始化)。需結合健康檢查實現真正的依賴就緒。
1. 配置健康檢查
為MySQL添加健康檢查,確保數據庫就緒後再啓動後端:
services:
mysql:
image: mysql:8.0
# 健康檢查:每10秒執行一次,超時5秒,3次成功視為健康
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s # 啓動後30秒再開始健康檢查(給初始化留時間)
backend:
depends_on:
mysql:
condition: service_healthy # 僅當mysql健康時才啓動
這樣backend會等待MySQL完全就緒(能ping通)後再啓動,避免連接失敗。
五、容器擴展與負載均衡
開發環境可能需要多個後端實例模擬負載均衡,Compose的--scale參數可快速擴展服務:
# 啓動3個backend實例
docker-compose up -d --scale backend=3
配合Nginx的負載均衡配置(nginx.conf):
http {
upstream backend {
# 引用backend服務的3個實例(Compose會自動解析為容器IP)
server backend:8080;
}
server {
listen 80;
location /api/ {
proxy_pass http://backend/; # 反向代理到backend集羣
}
}
}
訪問http://localhost/api/時,Nginx會將請求分發到3個backend實例,實現簡單的負載均衡。
六、最佳實踐與避坑指南
- 不要依賴默認網絡:生產環境建議自定義網絡,通過網絡隔離增強安全性。
- 數據卷命名規範:使用項目名+服務名命名數據卷(如
myapp_mysql-data),避免不同項目的數據卷衝突。 - 避免在Compose中存儲敏感信息:密碼、密鑰等敏感信息應通過環境變量文件或外部密鑰管理服務注入,且
.env文件不要提交到代碼倉庫。 - 控制容器資源:為避免單個容器耗盡宿主機資源,可限制CPU和內存:
services:
backend:
deploy:
resources:
limits:
cpus: '0.5' # 最多使用0.5個CPU核心
memory: 512M # 最多使用512MB內存
- 定期清理無用資源:使用
docker-compose down --rmi local清理本地構建的鏡像,避免磁盤佔用過大。
總結
Docker Compose通過簡潔的YAML配置實現了多容器應用的編排,解決了手動管理容器的繁瑣問題。進階用法中,自定義網絡實現服務隔離、健康檢查確保依賴就緒、環境變量文件適配多環境,這些技巧能讓你的部署配置更靈活、更可靠。
雖然Compose主要用於開發和測試環境,但其編排思想也適用於生產環境的容器管理(如Kubernetes)。掌握Compose的進階用法,不僅能提升日常開發效率,也能為理解更復雜的容器編排平台打下基礎。