將堆疊部署到叢集

在 Swarm 模式下執行 Docker Engine 時,您可以使用 docker stack deploy 將完整的應用程式堆疊部署到 Swarm。 deploy 命令接受 Compose 檔案 形式的堆疊描述。

注意

docker stack deploy 命令使用 Compose V1 所使用的舊版 Compose 檔案版本 3 格式。 由 Compose 規格 定義的最新格式與 docker stack deploy 命令不相容。

有關 Compose 演進的更多資訊,請參閱 Compose 歷史記錄

要完成本教學課程,您需要

  1. Swarm 模式 下執行的 Docker Engine。 如果您不熟悉 Swarm 模式,您可能需要閱讀 Swarm 模式主要概念服務的運作方式

    注意

    如果您在本地開發環境中進行測試,您可以使用 docker swarm init 將您的引擎設定為 Swarm 模式。

    如果您已經有一個多節點 Swarm 正在執行,請記住所有 docker stackdocker service 命令都必須從管理節點執行。

  2. 最新版本的 Docker Compose

設定 Docker Registry

由於 Swarm 由多個 Docker Engine 組成,因此需要 Registry 將映像檔分發給所有 Engine。 您可以使用 Docker Hub 或維護您自己的 Registry。以下是如何建立一個用完即棄的 Registry。

  1. 將 Registry 作為服務啟動於您的 Swarm 上

    $ docker service create --name registry --publish published=5000,target=5000 registry:2
    
  2. 使用 docker service ls 檢查其狀態

    $ docker service ls
    
    ID            NAME      REPLICAS  IMAGE                                                                               COMMAND
    l7791tpuwkco  registry  1/1       registry:2@sha256:1152291c7f93a4ea2ddc95e46d142c31e743b6dd70e194af9e6ebe530f782c17
    

    一旦 REPLICAS 下顯示 1/1,它就正在執行。如果顯示 0/1,它可能仍在提取映像檔。

  3. 使用 curl 檢查它是否正常運作

    $ curl http://localhost:5000/v2/
    
    {}
    

建立範例應用程式

本指南中使用的應用程式基於 Docker Compose 快速入門 指南中的點擊計數器應用程式。它由一個 Python 應用程式組成,該應用程式在 Redis 實例中維護一個計數器,並在您每次訪問時增加計數器。

  1. 建立專案目錄

    $ mkdir stackdemo
    $ cd stackdemo
    
  2. 在專案目錄中建立一個名為 app.py 的檔案,並將以下程式碼貼上進去

    from flask import Flask
    from redis import Redis
    
    app = Flask(__name__)
    redis = Redis(host='redis', port=6379)
    
    @app.route('/')
    def hello():
        count = redis.incr('hits')
        return 'Hello World! I have been seen {} times.\n'.format(count)
    
    if __name__ == "__main__":
        app.run(host="0.0.0.0", port=8000, debug=True)
  3. 建立一個名為 requirements.txt 的檔案,並將這兩行程式碼貼上進去

    flask
    redis
  4. 建立一個名為 Dockerfile 的檔案,並將以下程式碼貼上進去

    # syntax=docker/dockerfile:1
    FROM python:3.4-alpine
    ADD . /code
    WORKDIR /code
    RUN pip install -r requirements.txt
    CMD ["python", "app.py"]
  5. 建立一個名為 compose.yml 的檔案,並將以下程式碼貼上進去

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

    Web 應用程式的映像檔是使用上面定義的 Dockerfile 建立的。它也被標記為 127.0.0.1:5000 - 先前建立的 Registry 的地址。這在將應用程式分發到 Swarm 時非常重要。

使用 Compose 測試應用程式

  1. 使用 docker compose up 啟動應用程式。這將建置 Web 應用程式映像檔,如果您還沒有 Redis 映像檔,它會提取該映像檔,並建立兩個容器。

    您會看到一個關於 Engine 處於 Swarm 模式的警告。這是因為 Compose 沒有利用 Swarm 模式,而是將所有內容都部署到單一節點。您可以放心地忽略它。

    $ docker compose up -d
    
    WARNING: The Docker Engine you're using is running in swarm mode.
    
    Compose does not use swarm mode to deploy services to multiple nodes in
    a swarm. All containers are scheduled on the current node.
    
    To deploy your application across the swarm, use `docker stack deploy`.
    
    Creating network "stackdemo_default" with the default driver
    Building web
    ...(build output)...
    Creating stackdemo_redis_1
    Creating stackdemo_web_1
    
  2. 使用 docker compose ps 檢查應用程式是否正在執行

    $ docker compose ps
    
          Name                     Command               State           Ports
    -----------------------------------------------------------------------------------
    stackdemo_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp
    stackdemo_web_1     python app.py                    Up      0.0.0.0:8000->8000/tcp
    

    您可以使用 curl 測試應用程式

    $ curl http://localhost:8000
    Hello World! I have been seen 1 times.
    
    $ curl http://localhost:8000
    Hello World! I have been seen 2 times.
    
    $ curl http://localhost:8000
    Hello World! I have been seen 3 times.
    
  3. 關閉應用程式

    $ docker compose down --volumes
    
    Stopping stackdemo_web_1 ... done
    Stopping stackdemo_redis_1 ... done
    Removing stackdemo_web_1 ... done
    Removing stackdemo_redis_1 ... done
    Removing network stackdemo_default
    

將產生的映像檔推送至 Registry

要將 Web 應用程式的映像檔散佈到整個 Swarm,需要將它推送到您先前設定的 Registry。使用 Compose,這非常簡單。

$ docker compose push

Pushing web (127.0.0.1:5000/stackdemo:latest)...
The push refers to a repository [127.0.0.1:5000/stackdemo]
5b5a49501a76: Pushed
be44185ce609: Pushed
bd7330a79bcf: Pushed
c9fc143a069a: Pushed
011b303988d2: Pushed
latest: digest: sha256:a81840ebf5ac24b42c1c676cbda3b2cb144580ee347c07e1bc80e35e5ca76507 size: 1372

堆疊現在已準備好部署。

將堆疊部署到 Swarm

  1. 使用 docker stack deploy 建立堆疊。

    $ docker stack deploy --compose-file compose.yml stackdemo
    
    Ignoring unsupported options: build
    
    Creating network stackdemo_default
    Creating service stackdemo_web
    Creating service stackdemo_redis
    

    最後一個參數是堆疊的名稱。每個網路、磁碟區和服務名稱都會加上堆疊名稱作為前綴。

  2. 使用 docker stack services stackdemo 檢查它是否正在執行。

    $ docker stack services stackdemo
    
    ID            NAME             MODE        REPLICAS  IMAGE
    orvjk2263y1p  stackdemo_redis  replicated  1/1       redis:3.2-alpine@sha256:f1ed3708f538b537eb9c2a7dd50dc90a706f7debd7e1196c9264edeea521a86d
    s1nf0xy8t1un  stackdemo_web    replicated  1/1       127.0.0.1:5000/stackdemo@sha256:adb070e0805d04ba2f92c724298370b7a4eb19860222120d43e0f6351ddbc26f
    

    一旦它開始執行,您應該會在兩個服務的 REPLICAS 下看到 1/1。如果您有多節點 Swarm,這可能需要一些時間,因為需要提取映像檔。

    與之前一樣,您可以使用 curl 測試應用程式。

    $ curl http://localhost:8000
    Hello World! I have been seen 1 times.
    
    $ curl http://localhost:8000
    Hello World! I have been seen 2 times.
    
    $ curl http://localhost:8000
    Hello World! I have been seen 3 times.
    

    使用 Docker 內建的路由網格,您可以透過連接埠 8000 存取 Swarm 中的任何節點,並將請求路由到應用程式。

    $ curl http://address-of-other-node:8000
    Hello World! I have been seen 4 times.
    
  3. 使用 docker stack rm 關閉堆疊。

    $ docker stack rm stackdemo
    
    Removing service stackdemo_web
    Removing service stackdemo_redis
    Removing network stackdemo_default
    
  4. 使用 docker service rm 關閉 Registry。

    $ docker service rm registry
    
  5. 如果您只是在本地機器上進行測試,並且想要將 Docker 引擎退出 Swarm 模式,請使用 docker swarm leave

    $ docker swarm leave --force
    
    Node left the swarm.