使用 Docker Compose

Docker Compose 是一個協助您定義和分享多容器應用程式的工具。使用 Compose,您可以建立 YAML 檔案來定義服務,並使用單一指令啟動或刪除所有內容。

使用 Compose 的一大優點是您可以將應用程式堆疊定義在檔案中,將其保存在專案儲存庫的根目錄(現在已進行版本控制),並輕鬆讓其他人貢獻您的專案。其他人只需複製您的儲存庫並使用 Compose 啟動應用程式即可。事實上,您現在可能會在 GitHub/GitLab 上看到不少專案正是這樣做的。

建立 Compose 檔案

getting-started-app 目錄中,建立一個名為 compose.yaml 的檔案。

├── getting-started-app/
│ ├── Dockerfile
│ ├── compose.yaml
│ ├── node_modules/
│ ├── package.json
│ ├── spec/
│ ├── src/
│ └── yarn.lock

定義應用程式服務

第 6 部分 中,您使用以下指令來啟動應用程式服務。

$ docker run -dp 127.0.0.1:3000:3000 \
  -w /app -v "$(pwd):/app" \
  --network todo-app \
  -e MYSQL_HOST=mysql \
  -e MYSQL_USER=root \
  -e MYSQL_PASSWORD=secret \
  -e MYSQL_DB=todos \
  node:18-alpine \
  sh -c "yarn install && yarn run dev"

您現在將在 compose.yaml 檔案中定義此服務。

  1. 在文字或程式碼編輯器中開啟 compose.yaml,並首先定義您想要作為應用程式一部分執行的第一個服務(或容器)的名稱和映像檔。該名稱將自動成為網路別名,這在定義 MySQL 服務時會很有用。

    services:
      app:
        image: node:18-alpine
  2. 通常,您會看到 command 靠近 image 定義,雖然沒有順序要求。將 command 新增到您的 compose.yaml 檔案。

    services:
      app:
        image: node:18-alpine
        command: sh -c "yarn install && yarn run dev"
  3. 現在,透過定義服務的 ports 來遷移指令的 -p 127.0.0.1:3000:3000 部分。

    services:
      app:
        image: node:18-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 127.0.0.1:3000:3000
  4. 接下來,使用 working_dirvolumes 定義來遷移工作目錄 (-w /app) 和磁碟區映射 (-v "$(pwd):/app")。

    Docker Compose 磁碟區定義的其中一個優點是您可以使用目前目錄的相對路徑。

    services:
      app:
        image: node:18-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 127.0.0.1:3000:3000
        working_dir: /app
        volumes:
          - ./:/app
  5. 最後,您需要使用 environment 鍵來遷移環境變數定義。

    services:
      app:
        image: node:18-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 127.0.0.1:3000:3000
        working_dir: /app
        volumes:
          - ./:/app
        environment:
          MYSQL_HOST: mysql
          MYSQL_USER: root
          MYSQL_PASSWORD: secret
          MYSQL_DB: todos

定義 MySQL 服務

現在,是時候定義 MySQL 服務了。您用於該容器的指令如下:

$ docker run -d \
  --network todo-app --network-alias mysql \
  -v todo-mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=todos \
  mysql:8.0
  1. 首先定義新的服務並將其命名為 mysql,以便它自動取得網路別名。同時也指定要使用的映像檔。

    
    services:
      app:
        # The app service definition
      mysql:
        image: mysql:8.0
  2. 接下來,定義磁碟區映射。當您使用 docker run 執行容器時,Docker 會自動建立具名磁碟區。但是,使用 Compose 執行時不會發生這種情況。您需要在頂層 volumes: 區段中定義磁碟區,然後在服務設定中指定掛載點。只需提供磁碟區名稱,就會使用預設選項。

    services:
      app:
        # The app service definition
      mysql:
        image: mysql:8.0
        volumes:
          - todo-mysql-data:/var/lib/mysql
    
    volumes:
      todo-mysql-data:
  3. 最後,您需要指定環境變數。

    services:
      app:
        # The app service definition
      mysql:
        image: mysql:8.0
        volumes:
          - todo-mysql-data:/var/lib/mysql
        environment:
          MYSQL_ROOT_PASSWORD: secret
          MYSQL_DATABASE: todos
    
    volumes:
      todo-mysql-data:

此時,您完整的 compose.yaml 檔案應該如下所示:

services:
  app:
    image: node:18-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 127.0.0.1:3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: secret
      MYSQL_DB: todos

  mysql:
    image: mysql:8.0
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:

執行應用程式堆疊

現在您有了 compose.yaml 檔案,您可以啟動您的應用程式了。

  1. 首先請確定沒有其他容器副本正在執行。使用 docker ps 列出容器,並使用 docker rm -f <ids> 將它們移除。

  2. 使用 docker compose up 指令啟動應用程式堆疊。新增 -d 旗標可在背景執行所有內容。

    $ docker compose up -d
    

    當您執行前一個指令時,您應該會看到如下輸出:

    Creating network "app_default" with the default driver
    Creating volume "app_todo-mysql-data" with default driver
    Creating app_app_1   ... done
    Creating app_mysql_1 ... done

    您會注意到 Docker Compose 建立了磁碟區以及網路。預設情況下,Docker Compose 會自動建立專門用於應用程式堆疊的網路(這就是為什麼您沒有在 Compose 檔案中定義網路的原因)。

  3. 使用 docker compose logs -f 指令檢視記錄。您會看到來自每個服務的記錄交錯成單一流。當您想要觀察與時序相關的問題時,這非常有用。-f 旗標會追蹤記錄,因此會在產生時提供即時輸出。

    如果您已經執行過該指令,您會看到如下所示的輸出:

    mysql_1  | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections.
    mysql_1  | Version: '8.0.31'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
    app_1    | Connected to mysql db at host mysql
    app_1    | Listening on port 3000

    服務名稱顯示在行的開頭(通常是彩色的),以協助區分訊息。如果您想要檢視特定服務的記錄,您可以將服務名稱新增到記錄指令的結尾(例如,docker compose logs -f app)。

  4. 此時,您應該能夠在瀏覽器中開啟您的應用程式,網址為 http://localhost:3000 並看到它正在執行。

在 Docker Desktop 儀表板中檢視應用程式堆疊

如果您檢視 Docker Desktop 儀表板,您會看到有一個名為 **getting-started-app** 的群組。這是 Docker Compose 的專案名稱,用於將容器組合在一起。預設情況下,專案名稱只是 compose.yaml 所在目錄的名稱。

如果您展開堆疊,您會看到您在 Compose 檔案中定義的兩個容器。名稱也更具描述性,因為它們遵循 <服務名稱>-<副本編號> 的模式。因此,可以很容易地快速看出哪個容器是您的應用程式,哪個容器是 mysql 資料庫。

全部刪除

當您準備好刪除所有內容時,只需執行 docker compose down 或點選 Docker Desktop 儀表板上的垃圾桶圖示即可刪除整個應用程式。容器將停止,網路將被移除。

警告

預設情況下,當您執行 docker compose down 時,compose 檔案中的具名磁碟區不會被移除。如果您想要移除磁碟區,您需要新增 --volumes 旗標。

當您刪除應用程式堆疊時,Docker Desktop 儀表板不會移除磁碟區。

摘要

在本節中,您瞭解了 Docker Compose 以及它如何協助您簡化定義和分享多服務應用程式的方式。

相關資訊

後續步驟

接下來,您將瞭解一些可以用來改進 Dockerfile 的最佳實務。