将堆栈部署到 Swarm

当在Swarm模式下运行Docker Engine时,您可以使用 docker stack deploy 命令将完整的应用程序栈部署到Swarm中。docker stack deploy 命令接受以 Compose 文件格式提供的堆栈描述。

注意

The docker stack deploy 命令使用旧的 Compose 文件版本 3 格式,该格式被 Compose V1 使用。最新规范中定义的 Compose 规范docker stack deploy 命令不兼容。

有关 Compose 演变的更多信息,请参阅 Compose 历史

要完成本教程,您需要:

  1. 一个以 Swarm 模式运行的 Docker Engine。 如果您还不熟悉 Swarm 模式,您可能想要阅读 Swarm 模式核心概念服务如何工作

    注意

    如果您正在本地开发环境中进行测试, 您可以使用 docker swarm init 将您的引擎设置为 Swarm 模式。

    如果您已经运行了一个多节点群集,请牢记所有 docker stackdocker service 命令必须从管理节点(manager node)上运行。

  2. 当前版本的 Docker Compose

设置 Docker 注册表

由于集群由多个 Docker 引擎组成,因此需要一个镜像仓库来将镜像分发到所有引擎上。您可以使用 Docker Hub 或自行维护一个。以下是如何创建一个临时镜像仓库(之后可丢弃)的说明。

  1. 在您的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/
    
    {}
    

创建示例应用程序

本指南中使用的示例应用基于

  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——即之前创建的注册表地址。这在将应用程序分发到集群时非常重要。

使用 Compose 测试应用

  1. 使用 docker compose up 启动应用程序。这将构建 Web 应用程序镜像, 如果您尚未拥有 Redis 镜像,则会拉取该镜像,并创建两个 容器。

    您会看到一条关于引擎处于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
    

将生成的镜像推送到注册表

要将 Web 应用程序的镜像分发到 Swarm,需要将其推送到您之前设置的镜像仓库。使用 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

The stack is now ready to be deployed.

将栈部署到集群

  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 上的任何节点并路由到该应用:

    $ 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 将注册中心下线:

    $ docker service rm registry
    
  5. 如果您只是在本地机器上进行测试,并希望将 Docker Engine 退出 Swarm 模式,请使用 docker swarm leave

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