Docker Compose 快速入門

本教學旨在透過引導您開發基本的 Python 網頁應用程式來介紹 Docker Compose 的基本概念。

使用 Flask 框架,該應用程式在 Redis 中具有點擊計數器,提供 Docker Compose 如何應用於網頁開發情境的實際範例。

即使您不熟悉 Python,這裡展示的概念也應該是可以理解的。

這是一個非規範性的範例,僅重點說明您可以使用 Compose 執行的關鍵事項。

先決條件

請確認您已

  • 安裝最新版本的 Docker Compose
  • 對 Docker 概念和 Docker 的運作方式有基本的了解

步驟 1:設定

  1. 建立專案的目錄

    $ mkdir composetest
    $ cd composetest
    
  2. 在您的專案目錄中建立名為 app.py 的檔案,並貼上以下程式碼

    import time
    
    import redis
    from flask import Flask
    
    app = Flask(__name__)
    cache = redis.Redis(host='redis', port=6379)
    
    def get_hit_count():
        retries = 5
        while True:
            try:
                return cache.incr('hits')
            except redis.exceptions.ConnectionError as exc:
                if retries == 0:
                    raise exc
                retries -= 1
                time.sleep(0.5)
    
    @app.route('/')
    def hello():
        count = get_hit_count()
        return f'Hello World! I have been seen {count} times.\n'

    在此範例中,redis 是應用程式網路上的 redis 容器的主機名稱,並使用預設埠 6379

    **注意**

    請注意 get_hit_count 函式的撰寫方式。如果 Redis 服務無法使用,這個基本的重試迴圈會嘗試多次請求。這在應用程式啟動時很有用,同時也使應用程式更具彈性,如果 Redis 服務需要在應用程式生命週期中的任何時間重新啟動。在叢集中,這也有助於處理節點之間瞬間的連線中斷。

  3. 在您的專案目錄中建立另一個名為 requirements.txt 的檔案,並貼上以下程式碼

    flask
    redis
  4. 建立 Dockerfile 並貼上以下程式碼

    # syntax=docker/dockerfile:1
    FROM python:3.10-alpine
    WORKDIR /code
    ENV FLASK_APP=app.py
    ENV FLASK_RUN_HOST=0.0.0.0
    RUN apk add --no-cache gcc musl-dev linux-headers
    COPY requirements.txt requirements.txt
    RUN pip install -r requirements.txt
    EXPOSE 5000
    COPY . .
    CMD ["flask", "run", "--debug"]

    這告訴 Docker

    • 從 Python 3.10 映像檔開始建置映像檔。
    • 將工作目錄設定為 /code
    • 設定 flask 指令使用的環境變數。
    • 安裝 gcc 和其他相依性
    • 複製 requirements.txt 並安裝 Python 相依性。
    • 將中繼資料新增至映像檔,以描述容器正在接聽埠 5000
    • 將專案中的目前目錄 . 複製到映像檔中的工作目錄 .
    • 將容器的預設指令設定為 flask run --debug

    **重要**

    檢查 Dockerfile 沒有像 .txt 這樣的副檔名。某些編輯器可能會自動附加此副檔名,導致您執行應用程式時出錯。

    如需如何撰寫 Dockerfile 的詳細資訊,請參閱 Dockerfile 參考

步驟 2:在 Compose 檔案中定義服務

Compose 簡化了對整個應用程式堆疊的控制,讓您可以在單個、易於理解的 YAML 設定檔中輕鬆管理服務、網路和磁碟區。

在您的專案目錄中建立一個名為 compose.yaml 的檔案,並貼上以下內容

services:
  web:
    build: .
    ports:
      - "8000:5000"
  redis:
    image: "redis:alpine"

這個 Compose 檔案定義了兩個服務:webredis

web 服務使用從目前目錄中的 Dockerfile 建置的映像檔。然後,它將容器和主機繫結到公開的埠 8000。這個範例服務使用 Flask 網頁伺服器的預設埠 5000

redis 服務使用從 Docker Hub 儲存庫拉取的公開 Redis 映像檔。

有關 compose.yaml 檔案的更多資訊,請參閱 Compose 的運作方式

步驟 3:使用 Compose 建置和執行您的應用程式

使用單一指令,您可以從您的設定檔建立並啟動所有服務。

  1. 在您的專案目錄中,透過執行 docker compose up 來啟動您的應用程式。

    $ docker compose up
    
    Creating network "composetest_default" with the default driver
    Creating composetest_web_1 ...
    Creating composetest_redis_1 ...
    Creating composetest_web_1
    Creating composetest_redis_1 ... done
    Attaching to composetest_web_1, composetest_redis_1
    web_1    |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
    redis_1  | 1:C 17 Aug 22:11:10.480 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
    redis_1  | 1:C 17 Aug 22:11:10.480 # Redis version=4.0.1, bits=64, commit=00000000, modified=0, pid=1, just started
    redis_1  | 1:C 17 Aug 22:11:10.480 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
    web_1    |  * Restarting with stat
    redis_1  | 1:M 17 Aug 22:11:10.483 * Running mode=standalone, port=6379.
    redis_1  | 1:M 17 Aug 22:11:10.483 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
    web_1    |  * Debugger is active!
    redis_1  | 1:M 17 Aug 22:11:10.483 # Server initialized
    redis_1  | 1:M 17 Aug 22:11:10.483 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
    web_1    |  * Debugger PIN: 330-787-903
    redis_1  | 1:M 17 Aug 22:11:10.483 * Ready to accept connections
    

    Compose 會拉取 Redis 映像檔,為您的程式碼建置映像檔,並啟動您定義的服務。在這種情況下,程式碼會在建置時靜態複製到映像檔中。

  2. 在瀏覽器中輸入 https://127.0.0.1:8000/ 以查看正在執行的應用程式。

    如果這無法解決,您也可以嘗試 http://127.0.0.1:8000

    您應該會在瀏覽器中看到一條訊息,顯示

    Hello World! I have been seen 1 times.
    hello world in browser
  3. 重新整理頁面。

    數字應該會遞增。

    Hello World! I have been seen 2 times.
    hello world in browser
  4. 切換到另一個終端機視窗,然後輸入 docker image ls 以列出本機映像檔。

    此時列出映像檔應該會返回 redisweb

    $ docker image ls
    
    REPOSITORY        TAG           IMAGE ID      CREATED        SIZE
    composetest_web   latest        e2c21aa48cc1  4 minutes ago  93.8MB
    python            3.4-alpine    84e6077c7ab6  7 days ago     82.5MB
    redis             alpine        9d8fa9aa0e5b  3 weeks ago    27.5MB
    

    您可以使用 docker inspect <標籤或 ID> 檢查映像檔。

  5. 停止應用程式,方法是在第二個終端機的專案目錄中執行 docker compose down,或是在啟動應用程式的原始終端機中按下 CTRL+C

步驟 4:編輯 Compose 檔案以使用 Compose Watch

編輯專案目錄中的 compose.yaml 檔案以使用 watch,以便您預覽正在執行的 Compose 服務,這些服務會在您編輯和儲存程式碼時自動更新

services:
  web:
    build: .
    ports:
      - "8000:5000"
    develop:
      watch:
        - action: sync
          path: .
          target: /code
  redis:
    image: "redis:alpine"

每當檔案變更時,Compose 就會將檔案同步到容器內 /code 下的對應位置。複製後,打包器會在不停機的情況下更新正在執行的應用程式。

有關 Compose Watch 如何運作的更多資訊,請參閱 使用 Compose Watch。或者,請參閱 管理容器中的資料 以了解其他選項。

**注意**

為了讓此範例正常運作,已將 --debug 選項新增到 Dockerfile 中。Flask 中的 --debug 選項可啟用自動程式碼重新載入,讓您無需重新啟動或重建容器即可處理後端 API。變更 .py 檔案後,後續的 API 呼叫將使用新的程式碼,但在這個小型範例中,瀏覽器 UI 不會自動重新整理。大多數前端開發伺服器都包含與 Compose 搭配使用的原生即時重新載入支援。

步驟 5:使用 Compose 重新建置和執行應用程式

在您的專案目錄中,輸入 docker compose watchdocker compose up --watch 以建置並啟動應用程式,並啟動檔案監看模式。

$ docker compose watch
[+] Running 2/2
 ✔ Container docs-redis-1 Created                                                                                                                                                                                                        0.0s
 ✔ Container docs-web-1    Recreated                                                                                                                                                                                                      0.1s
Attaching to redis-1, web-1
         ⦿ watch enabled
...

再次在網頁瀏覽器中檢查「Hello World」訊息,並重新整理以查看計數遞增。

步驟 6:更新應用程式

要查看 Compose Watch 的實際運作方式

  1. 變更 app.py 中的問候語並儲存。例如,將 Hello World! 訊息變更為 Hello from Docker!

    return f'Hello from Docker! I have been seen {count} times.\n'
  2. 在瀏覽器中重新整理應用程式。問候語應該已更新,計數器應該仍在遞增。

    hello world in browser
  3. 完成後,執行 docker compose down

步驟 7:分割您的服務

使用多個 Compose 檔案可讓您針對不同的環境或工作流程自訂 Compose 應用程式。這對於可能使用數十個容器的大型應用程式很有用,其所有權分佈在多個團隊中。

  1. 在您的專案資料夾中,建立一個名為 infra.yaml 的新 Compose 檔案。

  2. 從您的 compose.yaml 檔案中剪下 Redis 服務,並將其貼到您的新 infra.yaml 檔案中。請確定您在檔案頂部新增了最上層屬性 services。您的 infra.yaml 檔案現在看起來應該像這樣

    services:
      redis:
        image: "redis:alpine"
  3. 在您的 compose.yaml 檔案中,新增最上層屬性 include 以及 infra.yaml 檔案的路徑。

    include:
       - infra.yaml
    services:
      web:
        build: .
        ports:
          - "8000:5000"
        develop:
          watch:
            - action: sync
              path: .
              target: /code
  4. 執行 docker compose up 以使用更新的 Compose 檔案建置應用程式並執行它。您應該會在瀏覽器中看到「Hello world」訊息。

這是一個簡化的範例,但它展示了 include 的基本原理,以及它如何更容易將複雜的應用程式模組化成子 Compose 檔案。有關 include 和使用多個 Compose 檔案的更多資訊,請參閱 使用多個 Compose 檔案

步驟 8:試用其他一些指令

  • 如果您想在背景中執行服務,可以將 -d 旗標(代表「分離」模式)傳遞給 docker compose up,並使用 docker compose ps 查看目前正在執行的內容

    $ docker compose up -d
    
    Starting composetest_redis_1...
    Starting composetest_web_1...
    
    $ docker compose ps
    
           Name                      Command               State           Ports         
    -------------------------------------------------------------------------------------
    composetest_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp              
    composetest_web_1     flask run                        Up      0.0.0.0:8000->5000/tcp
    
  • 執行 docker compose --help 以查看其他可用的指令。

  • 如果您使用 docker compose up -d 啟動 Compose,請在完成服務後停止服務

    $ docker compose stop
    
  • 您可以使用 docker compose down 指令關閉所有內容,完全移除容器。

後續步驟