docker使用經驗總結(三、Docker compose基礎應用)

jpx發表於2024-08-19

六、Docker compose:Docker Compose 是一個用於定義和執行多容器 Docker 應用程式的工具。透過 Docker Compose,使用者可以使用一個 YAML 檔案來定義應用程式所需的所有服務,然後透過一條命令就可以建立並啟動這些服務。Docker Compose 可以極大簡化多容器應用的管理和部署流程。

它的原理,Docker Compose 主要依賴於兩個核心部分:

  • YAML 檔案 (docker-compose.yml):這個檔案用來描述多容器應用的各個服務以及它們之間的關係。透過定義各個服務的映象、網路、卷、埠對映等,Compose 可以在本地環境或生產環境中一致性地部署應用。

  • Docker Compose CLI:Docker 提供了一個命令列工具 docker-compose,使用者可以透過它來管理使用 docker-compose.yml 定義的服務。這些命令包括啟動、停止、重啟服務,檢視日誌等。

1. compose.yml:是 Docker Compose 用來定義多容器應用的核心配置檔案。它使用 YAML 語法描述服務、網路、卷和其他配置項。下面是一個典型的 docker-compose.yml 檔案結構及其各部分的詳細說明。

YAML 檔案不必須命名為 docker-compose.yml,但預設情況下,Docker Compose 會在當前目錄下查詢名為 docker-compose.yml 的檔案作為配置檔案。如果想使用其他名稱的 YAML 檔案,也完全可以,只需要在執行 Docker Compose 命令時顯式指定該檔案的路徑和名稱。

version: '3.8'  # 指定 Docker Compose 檔案的版本

services:  # 定義服務
  web:  # 服務名稱,可以是任意名稱
    image: nginx:alpine  # 使用的映象
    ports:
      - "8080:80"  # 埠對映:將主機的8080埠對映到容器的80埠
    volumes:
      - ./html:/usr/share/nginx/html  # 掛載本地目錄到容器中的路徑
    networks:
      - webnet  # 指定服務使用的網路
    depends_on:
      - app  # 指定依賴的服務,確保app服務在web服務之前啟動

  app:  # 另一個服務
    build: ./app  # 使用本地的Dockerfile構建映象
    command: python app.py  # 覆蓋預設命令
    volumes:
      - ./app:/app  # 掛載本地目錄到容器中
    environment:
      - DEBUG=1  # 設定環境變數
    networks:
      - webnet  # 指定服務使用的網路

volumes:  # 定義資料卷
  db_data:  # 卷名稱,可以在 services 中引用
    driver: local  # 指定驅動型別,這裡是本地驅動

networks:  # 定義網路
  webnet:  # 網路名稱
    driver: bridge  # 指定網路驅動型別

version

version 定義了 docker-compose.yml 檔案的版本,版本決定了可以使用的語法和功能。常見版本包括 '3.8''3''2' 等。一般建議使用較新的版本以確保相容最新功能。

services

services 是最核心的部分,定義了應用中所有的服務。每個服務包含以下常用配置項:

  • image: 指定要使用的 Docker 映象。如果該映象不存在,Compose 會自動從 Docker Hub 拉取。
  • build: 如果你希望構建自己的映象,可以使用 build 選項,通常指定一個包含 Dockerfile 的路徑。
  • ports: 埠對映,HOST:CONTAINER 格式,將主機的埠對映到容器內的埠。
  • volumes: 卷掛載,HOST_PATH:CONTAINER_PATH 格式,將主機的目錄或檔案掛載到容器內。
  • networks: 指定服務使用的網路。可以在下面的 networks 部分定義這些網路。
  • environment: 設定環境變數,可以在容器內訪問這些變數。
  • depends_on: 指定服務之間的依賴關係,確保某些服務在其他服務啟動之前啟動。
  • command: 覆蓋預設的容器啟動命令。
  • restart: 定義容器的重啟策略(如 alwayson-failure)。

volumes

volumes 用於定義和管理資料卷。資料卷用於持久化資料,即使容器被刪除,資料仍然存在。

  • driver: 定義卷的驅動型別,預設是 local

卷可以在 services 中引用,作為資料儲存的路徑。

networks

networks 用於定義服務之間的網路配置。

  • driver: 指定網路驅動型別,常見的有 bridgeoverlay 等。

網路可以被多個服務共享,用於服務之間的通訊。

2.常用基礎命令:Docker Compose 的命令大多數是在專案的根目錄下執行的,該目錄包含 docker-compose.yml 檔案。Docker Compose 會自動在當前目錄查詢 docker-compose.yml 檔案,並根據其中定義的內容執行相關操作。

# 啟動應用:命令會讀取當前目錄下的 docker-compose.yml 檔案,並啟動所有定義的服務。如果服務所需的映象不存在,Compose 會自動構建或拉取映象。如果想在後臺執行,可以加上 -d 引數
docker compose up -d

# 啟動已經存在的容器,而不會重新建立它們。如果容器已經存在但未執行,此命令可以用來重新啟動它們。

docker compose start


# 命令會停止所有正在執行的服務
docker compose stop

# 重啟服務,且在不指定服務名稱,docker-compose 將重啟所有服務
docker compose restart [SERVICE_NAME]

# 列出當前所有服務的狀態
docker compose ps

# 看指定服務的日誌。如果不指定服務名稱,則會檢視所有服務的日誌
docker compose logs [SERVICE_NAME]

# 執行一次性命令
docker compose run SERVICE_NAME COMMAND

# 在正在執行的容器中執行命令
docker compose exec # 在 docker-compose.yml 中定義了 build 選項,可以用這個命令來構建映象 docker compose build # 停止並刪除所有在 docker-compose.yml 中啟動的服務、網路和掛載的卷。如果你想刪除服務但保留卷資料,可以加上 --volumes 選項 docker compose down --volumes

其中,docker compose up有幾個引數要重點講下

# --scale SERVICE=NUM:指定服務的容器數量,例如可以擴充套件 web 服務到 3 個副本。
docker compose up --scale web=3

# 制構建服務映象,即使映象已經存在
docker compose up --build

# 刪除不在 docker-compose.yml 檔案中的多餘容器
docker compose up --remove-orphans

2. 使用流程

  • 定義應用環境:在 docker-compose.yml 檔案中定義應用程式所需的各個服務。
  • 啟動應用:使用 docker-compose up 命令啟動整個應用,Compose 會根據 docker-compose.yml 檔案建立並啟動所有服務。
  • 管理服務:使用 docker-compose 提供的其他命令,如 stop, start, restart,scale等來管理已經啟動的服務。
  • 刪除應用:透過 docker-compose down 命令停止並刪除所有服務及其相關資源。

3.實踐

假設有一個前後端分離的 Python + Django + MySQL + Redis + Vue + Nginx 專案,我們需要為各個元件編寫Dockerfile,並在 docker-compose.yml 檔案中配置服務。

目錄結構:

myproject/
├── backend/
│   ├── Dockerfile
│   ├── myproject/
│   ├── manage.py
│   ├── requirements.txt
├── frontend/
│   ├── Dockerfile
│   ├── package.json
│   ├── src/
│   └── ...
├── nginx/
│   ├── Dockerfile
│   ├── nginx.conf
├── docker-compose.yml

3.1 Backend(Django)部分

backend/Dockerfile:

# 使用官方的 Python 映象作為基礎映象
FROM python:3.9-slim

# 設定工作目錄
WORKDIR /app

# 複製依賴檔案並安裝
COPY requirements.txt /app/
RUN pip install --no-cache-dir -r requirements.txt

# 複製應用程式碼
COPY . /app/

# 暴露應用埠
EXPOSE 8000

# 執行 Django 開發伺服器(你可能需要使用 gunicorn 或者其他 WSGI 伺服器在生產環境中)
CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"]

backend/requirements.txt,在這個檔案中,列出 Django 專案所需的所有 Python 包,如:

Django>=3.2,<4.0
mysqlclient
redis
gunicorn

3.2 Frontend(Vue.js)部分

frontend/Dockerfile:

# 使用 Node.js 映象作為基礎映象
FROM node:14-alpine

# 設定工作目錄
WORKDIR /app

# 複製依賴檔案並安裝
COPY package.json yarn.lock /app/
RUN yarn install

# 複製原始碼
COPY . /app/

# 構建 Vue.js 應用
RUN yarn build

# 執行 Vue.js 應用(在開發時可能用 npm run serve;在生產環境中通常用 nginx 或 serve 靜態資源)
EXPOSE 8080
CMD ["yarn", "serve"]

3.3 Nginx 部分

nginx/Dockerfile:

# 使用官方 Nginx 映象作為基礎映象
FROM nginx:alpine

# 刪除預設的配置檔案
RUN rm /etc/nginx/conf.d/default.conf

# 複製自定義的 Nginx 配置檔案
COPY nginx.conf /etc/nginx/conf.d/

# 複製前端構建的靜態檔案到 Nginx 容器
COPY --from=frontend /app/dist /usr/share/nginx/html

# 暴露埠
EXPOSE 80

nginx/nginx.conf: 這是一個 Nginx 配置檔案的示例,反向代理到 Django 和 Vue.js 應用

server {
    listen 80;

    # 靜態檔案處理(Vue.js)
    location / {
        root /usr/share/nginx/html;
        try_files $uri $uri/ /index.html;
    }

    # 代理請求到 Django 應用
    location /api/ {
        proxy_pass http://backend:8000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

3.4 Docker Compose 檔案

docker-compose.yml:

version: '3.8'

services:
  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: mydatabase
      MYSQL_USER: myuser
      MYSQL_PASSWORD: mypassword
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - backend

  redis:
    image: redis:alpine
    restart: always
    networks:
      - backend

  backend:
    build: ./backend
    command: ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"]
    volumes:
      - ./backend:/app
    ports:
      - "8000:8000"
    environment:
      - DATABASE_HOST=db
      - DATABASE_PORT=3306
      - DATABASE_NAME=mydatabase
      - DATABASE_USER=myuser
      - DATABASE_PASSWORD=mypassword
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    depends_on:
      - db
      - redis
    networks:
      - backend

  frontend:
    build: ./frontend
    volumes:
      - ./frontend:/app
    ports:
      - "8080:8080"
    networks:
      - frontend

  nginx:
    build: ./nginx
    ports:
      - "80:80"
    depends_on:
      - frontend
      - backend
    networks:
      - frontend
      - backend

volumes:
  db_data:

networks:
  frontend:
  backend:

啟動專案:在 myproject/ 目錄下執行命令:docker compose up --build -d. 啟動所有服務。透過 http://localhost 訪問前端應用,後端 API 在 http://localhost/api/ 路徑下。

相關文章