在 Docker 的生態系統中,有三個工具被廣大開發者親切地稱為“Docker 三劍客”:Docker MachineDocker ComposeDocker Swarm。它們分別解決了不同層面的問題:

  • Docker Machine:負責在各種環境(本地、雲服務器)中快速創建和配置 Docker 主機。
  • Docker Swarm:Docker 原生的容器編排工具,用於管理集羣和調度服務。
  • Docker Compose今天的主角,它的核心使命是定義和運行多容器的 Docker 應用。

隨着 Docker Swarm 模式被集成進 Docker Engine,現在通常所説的“三劍客”更多是指 Docker 在單機和多容器應用編排上的核心工具集,而 Docker Compose 無疑是其中使用最頻繁、最接地氣的一個。

一、什麼是 Docker Compose?為什麼需要它?

想象一下,一個典型的 Web 應用可能包含以下組件:

  1. 一個用 Python/Node.js 編寫的應用容器。
  2. 一個 Nginx 容器作為反向代理。
  3. 一個 Redis 容器作為緩存。
  4. 一個 PostgreSQL 容器作為數據庫。

如果使用基礎的 docker run 命令,你需要為每個容器手動設置網絡、卷、環境變量、依賴關係等。這不僅命令冗長複雜,而且難以維護和重現。

Docker Compose 應運而生。它是一個用於定義和運行多容器 Docker 應用程序的工具。通過一個單獨的 docker-compose.yml 配置文件,你可以使用 YAML 語言來配置應用程序的所有服務。然後,只需一個簡單的命令,就能創建並啓動所有服務。

它的核心價值在於:

  • 簡化操作:一條命令替代一系列複雜的 docker run 指令。
  • 環境標準化:確保開發、測試、生產環境的一致性。
  • 高效管理:輕鬆管理整個應用的生命週期(啓動、停止、重建)。
  • 快速搭建開發環境:新成員只需拉取代碼和配置文件,執行 docker-compose up 即可獲得一個完整、隔離的開發環境。

二、Docker Compose 的核心概念與工作原理

1. 核心概念

  • 項目:一個由多個服務組成的完整應用。默認情況下,項目名稱取自其所在目錄的名稱。
  • 服務:一個應用容器的一個運行實例,對應 docker-compose.yml 文件中的一個 service。例如,一個 web 服務,一個 db 服務。
  • 容器:服務的實際運行實例。一個服務通常對應一個容器,但也可以通過 scale 命令擴展到多個容器實例。

2. 工作原理

Docker Compose 的核心是一個名為 docker-compose.yml 的 YAML 文件。當你執行 docker-compose up 時:

  1. 解析 YAML:Compose 讀取 docker-compose.yml 文件,解析其中定義的服務、網絡、卷等資源。
  2. 創建項目默認網絡:Compose 會自動為整個項目創建一個獨立的網絡,使得所有服務可以通過服務名作為主機名互相發現和通信。
  3. 構建鏡像(如需要):如果配置中指定了 build 路徑,Compose 會根據 Dockerfile 構建鏡像。
  4. 創建並啓動容器:根據配置為每個服務創建並啓動容器,自動處理容器間的依賴關係(depends_on)、數據卷掛載、端口映射等。
  5. 聚合日誌:將所有服務的日誌輸出聚合到同一個終端流中,方便查看。

三、詳解 docker-compose.yml 文件

這是一個標準的 docker-compose.yml 文件的結構示例和常用指令:

# 指定 Compose 文件的版本。建議使用 3.x 版本以兼容新特性。
version: '3.8'

# 定義本項目中的所有服務(容器)
services:
  # 服務一:Web 應用
  web:
    # 構建鏡像的上下文路徑,Compose 會使用該路徑下的 Dockerfile
    build: .
    #  alternatively, 可以直接使用已有的鏡像
    # image: my-python-app:latest
   
    # 將主機端口映射到容器端口 (主機端口:容器端口)
    ports:
      - "8000:5000"
   
    # 將主機目錄或卷掛載到容器中
    volumes:
      - .:/code
      - static_volume:/static_files
   
    # 設置環境變量
    environment:
      - DEBUG=1
      - DATABASE_URL=postgresql://user:password@db:5432/mydb
    # 或者使用環境變量文件
    # env_file:
    #   - .env
   
    # 定義服務間的依賴關係,Compose 會先啓動 db 再啓動 web
    depends_on:
      - db
      - redis
   
    # 容器啓動後執行的命令(會覆蓋 Dockerfile 中的 CMD)
    command: python app.py

  # 服務二:數據庫
  db:
    image: postgres:13
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=mydb
    # 將命名卷掛載到容器內的數據庫存儲路徑,實現數據持久化
    volumes:
      - postgres_data:/var/lib/postgresql/data

  # 服務三:緩存
  redis:
    image: redis:alpine
    # 限制容器使用的最大內存
    mem_limit: 128m

# 定義本項目中使用到的所有數據卷,需要在 services 之外聲明
volumes:
  postgres_data:
  static_volume:

常用指令説明:

  • build & image:指定服務的鏡像來源。
  • ports:端口映射。
  • volumes:數據卷掛載,用於數據持久化和代碼同步。
  • environment & env_file:環境配置。
  • depends_on:表達服務間的啓動依賴(注意:它不等待服務“就緒”,僅等待“運行”)。
  • networks:自定義網絡(默認會自動創建)。
  • command:覆蓋默認的啓動命令。

四、常用 Docker Compose 命令

掌握了 YAML 文件的編寫,操作就變得非常簡單:

  • 啓動所有服務docker-compose up
    • 後台啓動:docker-compose up -d
  • 停止並移除所有容器、網絡docker-compose down
    • 同時移除數據卷:docker-compose down -v
  • 查看服務狀態docker-compose ps
  • 查看服務日誌docker-compose logs
    • 查看特定服務日誌:docker-compose logs -f web
  • 在運行中的服務中執行命令docker-compose exec <service_name> <command>
    • 例如:docker-compose exec db psql -U user mydb
  • 重新構建並啓動服務docker-compose up --build
  • 擴展服務實例數量docker-compose up --scale web=3 (需要配合負載均衡器)
  • 停止服務(不刪除容器)docker-compose stop
  • 啓動已停止的服務docker-compose start

五、實戰:搭建一個簡單的 Flask + Redis 計數器應用

讓我們通過一個完整的例子來鞏固所學。

1. 創建項目目錄

mkdir flask-redis-counter && cd flask-redis-counter

2. 創建 app.py (Flask 應用)

from flask import Flask
import redis
import os

app = Flask(__name__)
# 通過服務名 "redis" 連接,這是 Compose 網絡的核心特性
redis_client = redis.Redis(host='redis', port=6379, decode_responses=True)

@app.route('/')
def hello():
    count = redis_client.incr('hits')
    return f'Hello World! 本頁面已被訪問 {count} 次。\n'

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)

3. 創建 Dockerfile

FROM python:3.9-alpine

WORKDIR /code

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

CMD ["python", "app.py"]

4. 創建 requirements.txt

flask
redis

5. 創建 docker-compose.yml

version: '3.8'

services:
  web:
    build: .
    ports:
      - "8000:5000"
    # 依賴於 redis 服務
    depends_on:
      - redis
    # 掛載代碼目錄,便於開發時熱更新
    volumes:
      - .:/code
    environment:
      - FLASK_DEBUG=1

  redis:
    image: "redis:alpine"

6. 運行並測試 在項目根目錄下執行:

docker-compose up --build

訪問 http://localhost:8000,每次刷新頁面,計數器都會增加!

六、總結

Docker Compose 極大地簡化了多容器應用的管理複雜度,是 Docker 學習路徑上不可或缺的一環。它將“基礎設施即代碼”的理念落到了實處,讓開發者能夠通過一個簡單的配置文件,輕鬆駕馭複雜的容器化應用。

無論是用於本地開發、自動化測試,還是作為 CI/CD 流水線的一部分,Docker Compose 都能顯著提升效率和可維護性。熟練掌握它,你就真正握有了開啓現代化應用部署大門的鑰匙。