功能介紹
什麼是Docker Compose?
Docker Compose是Docker官方提供的工具,用於定義和運行多容器Docker應用程序。通過使用YAML文件來配置應用程序的服務,可以使用單個命令創建和啓動所有服務。
Docker Compose的作用
- 簡化多容器應用管理:通過一個配置文件管理多個容器
- 環境一致性:確保開發、測試和生產環境的一致性
- 快速部署:一鍵啓動整個應用棧
- 服務編排:定義服務之間的依賴關係和啓動順序
Docker Compose的核心概念
- 服務(Service):應用的一個組件,如數據庫、Web服務器等
- 項目(Project):由多個服務組成的完整應用
- Compose文件:定義服務配置的YAML文件
使用教程
安裝Docker Compose
# Docker Desktop已包含Compose,Linux需要單獨安裝
# 下載Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 添加執行權限
sudo chmod +x /usr/local/bin/docker-compose
# 驗證安裝
docker-compose --version
Compose文件基本結構
# docker-compose.yml
version: '3.8'
services:
# 服務定義
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
database:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpass
volumes:
- db-data:/var/lib/mysql
volumes:
# 卷定義
db-data:
常用Compose命令
# 啓動所有服務
docker-compose up
# 後台啓動所有服務
docker-compose up -d
# 查看服務狀態
docker-compose ps
# 查看服務日誌
docker-compose logs
# 實時查看服務日誌
docker-compose logs -f
# 停止服務
docker-compose stop
# 啓動已停止的服務
docker-compose start
# 重啓服務
docker-compose restart
# 停止並刪除容器、網絡
docker-compose down
# 刪除卷和鏡像
docker-compose down -v --rmi all
# 執行單個服務命令
docker-compose exec web ls /
Compose文件詳細配置
version: '3.8'
services:
web:
# 鏡像
image: nginx:alpine
# 構建配置
build:
context: .
dockerfile: Dockerfile
args:
- BUILD_ARG=value
# 端口映射
ports:
- "8080:80"
- "8443:443"
# 環境變量
environment:
- ENV_VAR=value
- DATABASE_URL=mysql://user:pass@db:3306/mydb
# 卷掛載
volumes:
- ./html:/usr/share/nginx/html
- web-data:/data
# 依賴服務
depends_on:
- database
# 網絡配置
networks:
- frontend
# 健康檢查
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
# 資源限制
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
database:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: myapp
volumes:
- db-data:/var/lib/mysql
networks:
- backend
volumes:
web-data:
db-data:
networks:
frontend:
backend:
案例講解
案例一:LAMP應用棧
# 創建項目目錄
mkdir lamp-stack && cd lamp-stack
# 創建docker-compose.yml
cat > docker-compose.yml << EOF
version: '3.8'
services:
# Apache + PHP服務
web:
image: php:8.0-apache
ports:
- "8080:80"
volumes:
- ./www:/var/www/html
depends_on:
- database
networks:
- frontend
- backend
# MySQL數據庫服務
database:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: myapp
MYSQL_USER: myuser
MYSQL_PASSWORD: mypass
volumes:
- db-data:/var/lib/mysql
networks:
- backend
ports:
- "3306:3306"
# PHPMyAdmin服務
phpmyadmin:
image: phpmyadmin/phpmyadmin
ports:
- "8081:80"
environment:
PMA_HOST: database
MYSQL_ROOT_PASSWORD: rootpass
depends_on:
- database
networks:
- backend
volumes:
db-data:
networks:
frontend:
backend:
EOF
# 創建Web目錄和簡單PHP文件
mkdir www
cat > www/index.php << EOF
<?php
\$servername = "database";
\$username = "myuser";
\$password = "mypass";
\$dbname = "myapp";
try {
\$pdo = new PDO("mysql:host=\$servername;dbname=\$dbname", \$username, \$password);
echo "Connected successfully<br>";
echo "Hello LAMP Stack!";
} catch(PDOException \$e) {
echo "Connection failed: " . \$e->getMessage();
}
?>
EOF
# 啓動應用
docker-compose up -d
# 查看服務狀態
docker-compose ps
# 測試應用
curl http://localhost:8080
# 訪問PHPMyAdmin
# 在瀏覽器中打開 http://localhost:8081
案例二:微服務應用
# 創建項目目錄
mkdir microservices && cd microservices
# 創建API服務
mkdir api-service
cat > api-service/app.py << EOF
from flask import Flask, jsonify
import os
app = Flask(__name__)
@app.route('/')
def home():
return jsonify({
'service': 'API Service',
'message': 'Hello from API service!'
})
@app.route('/health')
def health():
return jsonify({'status': 'healthy'})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
EOF
cat > api-service/requirements.txt << EOF
Flask==2.0.1
EOF
cat > api-service/Dockerfile << EOF
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]
EOF
# 創建前端服務
mkdir frontend-service
cat > frontend-service/index.html << EOF
<!DOCTYPE html>
<html>
<head>
<title>Microservices Demo</title>
</head>
<body>
Microservices Demo
<div id="api-response"></div>
<script>
fetch('http://api:5000/')
.then(response => response.json())
.then(data => {
document.getElementById('api-response').innerHTML = '<p>' + JSON.stringify(data) + '</p>';
});
</script>
</body>
</html>
EOF
cat > frontend-service/Dockerfile << EOF
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
EOF
# 創建docker-compose.yml
cat > docker-compose.yml << EOF
version: '3.8'
services:
# 負載均衡器
nginx:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- frontend
- api
networks:
- frontend-net
# 前端服務
frontend:
build: ./frontend-service
networks:
- frontend-net
# API服務
api:
build: ./api-service
networks:
- frontend-net
- backend-net
# Redis緩存
redis:
image: redis:alpine
networks:
- backend-net
# 數據庫
database:
image: postgres:13
environment:
POSTGRES_DB: myapp
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypass
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend-net
volumes:
db-data:
networks:
frontend-net:
backend-net:
EOF
# 創建Nginx配置
cat > nginx.conf << EOF
events {
worker_connections 1024;
}
http {
upstream frontend {
server frontend:80;
}
upstream api {
server api:5000;
}
server {
listen 80;
location / {
proxy_pass http://frontend;
}
location /api/ {
proxy_pass http://api/;
}
}
}
EOF
# 啓動微服務應用
docker-compose up -d
# 查看服務狀態
docker-compose ps
# 測試應用
curl http://localhost:8080
curl http://localhost:8080/api/
常見問題解答
Q1: 如何處理服務啓動順序問題?
A: Docker Compose提供了depends_on選項,但它只等待容器啓動,不等待應用就緒。可以使用以下方法解決:
version: '3.8'
services:
web:
image: my-web-app
depends_on:
database:
condition: service_healthy
# 或者使用自定義健康檢查
# depends_on:
# - database
database:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpass
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 20s
retries: 10
或者在應用中實現重試機制:
# 在啓動腳本中添加重試邏輯
#!/bin/bash
until mysql -h database -u root -prootpass -e "SELECT 1"; do
echo "Waiting for database..."
sleep 5
done
# 啓動應用
exec your-app-command
Q2: 如何在不同環境中使用不同的配置?
A: 可以使用多個Compose文件或環境變量:
# 方法1:使用多個Compose文件
# docker-compose.yml (基礎配置)
# docker-compose.override.yml (開發環境)
# docker-compose.prod.yml (生產環境)
# 開發環境
docker-compose up -d
# 生產環境
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# 方法2:使用環境變量
# docker-compose.yml
version: '3.8'
services:
web:
image: my-app:${TAG:-latest}
environment:
- ENV=${ENV:-development}
# 設置環境變量
export TAG=v1.0
export ENV=production
docker-compose up -d
Q3: 如何調試Compose應用?
A: 可以通過以下方式調試Compose應用:
# 1. 查看服務日誌
docker-compose logs service-name
# 2. 實時查看日誌
docker-compose logs -f service-name
# 3. 進入容器調試
docker-compose exec service-name /bin/bash
# 4. 查看網絡配置
docker-compose exec service-name ip addr show
# 5. 使用docker-compose config驗證配置
docker-compose config
# 6. 構建時不使用緩存
docker-compose build --no-cache
# 7. 強制重新創建容器
docker-compose up -d --force-recreate
最佳實踐
1. Compose文件組織最佳實踐
- 使用版本控制管理Compose文件
- 為不同環境創建不同的Compose文件
- 使用.env文件管理環境變量
- 合理命名服務和資源
- 添加註釋説明覆雜配置
2. 服務設計最佳實踐
- 一個服務一個進程原則
- 明確定義服務間的依賴關係
- 合理設置資源限制
- 配置健康檢查確保服務可用性
- 使用命名卷而非綁定掛載
3. 安全最佳實踐
- 不在Compose文件中硬編碼敏感信息
- 使用Docker secrets管理敏感數據
- 限制服務間的網絡訪問
- 定期更新基礎鏡像
- 使用非root用户運行容器
4. 性能優化實踐
- 合理規劃網絡結構
- 使用多階段構建減小鏡像大小
- 配置適當的資源限制
- 使用緩存卷提高構建速度
- 監控服務性能指標
命令速查表
| 命令 | 描述 |
|---|---|
docker-compose up |
啓動所有服務 |
docker-compose up -d |
後台啓動所有服務 |
docker-compose ps |
查看服務狀態 |
docker-compose logs |
查看服務日誌 |
docker-compose logs -f |
實時查看服務日誌 |
docker-compose exec <service> <command> |
在服務中執行命令 |
docker-compose stop |
停止服務 |
docker-compose start |
啓動已停止的服務 |
docker-compose restart |
重啓服務 |
docker-compose down |
停止並刪除容器、網絡 |
docker-compose down -v |
同時刪除卷 |
docker-compose build |
構建服務鏡像 |
docker-compose pull |
拉取服務鏡像 |
docker-compose config |
驗證並查看最終配置 |