在docker swarm集群中使用HEALTHCHECK解决服务更新不可用的问题

这是我们使用自建 docker swarm 集群后在部署时遇到的一个问题,使用 docker service update 命令更新服务时,

docker service update -d=false --force service_name

在更新的过程中服务有短暂的时间不能访问。

该服务中运行的是 asp.net core web api ,所使用的 Dockerfile 如下:

FROM microsoft/aspnetcore:1.1.2
ARG PROJECT
WORKDIR /app
COPY ${PROJECT}/publish .
RUN echo "dotnet ${PROJECT}.dll --urls http://*:80" > run.sh

通过在服务更新期间在另外一个容器中运行下面的 curl 命令捕捉这个问题:

while true;do curl -sSf -w '%{http_code}' cloud_api/alive;sleep 2;done

service update 期间不能访问所更新的服务时,curl 会出现下面的输出:

curl: (7) Failed to connect to cloud_api port 80: Connection refused
000

怀疑是容器启动后,asp.net core web api 站点没有立即开始工作,dotnet 命令启动站点也需要一定的时间。

针对这个怀疑点,在 Dockcefile 中添加 HEALTHCHECK 指令,这样可以让 docker 在容器启动后对容器内应用进行健康检查,检查通过才将容器投入使用。

HEALTHCHECK --interval=5s --timeout=20s 
   CMD curl -fs localhost/alive || exit 1

注:localhost/alive 是容器内应用实现的一个健康检查 url 。

添加 HEALTHCHECK 后重新构建镜像并部署,执行 service update 命令问题没有出现,搞定!

docker swarm集群搭建及使用shipyard UI管理

一、规划

1、swarm01作为manager节点,swarm02和swarm03作为worker节点。

# cat /etc/hosts
127.0.0.1   localhost
192.168.139.175  swarm01 
192.168.139.176  swarm02 
192.168.139.177  swarm03

2、配置SSH免密登陆

# ssh-keygen -t rsa -P ''
# ssh-copy-id -i .ssh/id_rsa.pub [email protected]
# ssh-copy-id -i .ssh/id_rsa.pub [email protected]

二、安装docker和ansible

1、安装配置ansible

# yum -y install ansible
# cat /etc/ansible/hosts | grep -v ^# | grep -v ^$
[node]
192.168.139.176
192.168.139.177
# sed -i "s/SELINUX=enforcing/SELINUX=disabled" /etc/selinux/config
# ansible node -m copy -a 'src=/etc/selinux/config dest=/etc/selinux/'
# systemctl stop firewalld
# systemctl disable firewalld
# ansible node -a 'systemctl stop firewalld'
# ansible node -a 'systemctl disable firewalld'

注:这里选择关闭防火墙,实际环境中可自行开放端口。

2、安装docker

  • 在manager节点安装docker
# yum install -y yum-utils device-mapper-persistent-data lvm2
# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# yum list docker-ce --showduplicates | sort -r
# yum -y install docker-ce
# docker --version
Docker version 17.06.0-ce, build 02c1d87
# systemctl start docker
# systemctl status docker
# systemctl enable docker
  • 使用ansible在worker节点安装docker
# ansible node -m copy -a 'src=/etc/yum.repos.d/docker-ce.repo dest=/etc/yum.repos.d/'
# ansible node -m yum -a "state=present name=docker-ce"
# ansible node -a 'docker --version'
192.168.139.173 | SUCCESS | rc=0 >>
Docker version 17.06.0-ce, build 02c1d87
192.168.139.174 | SUCCESS | rc=0 >>
Docker version 17.06.0-ce, build 02c1d87
# ansible node -a 'systemctl start docker'
# ansible node -a 'systemctl status docker'
# ansible node -a 'systemctl enable docker'

三、配置docker swarm集群

1、创建docker swarm集群

# docker swarm init --listen-addr 0.0.0.0
Swarm initialized: current node (a1tno675d14sm6bqlc512vf10) is now a manager.
To add a worker to this swarm, run the following command:
    docker swarm join --token SWMTKN-1-3sp9uxzokgr252u1jauoowv74930s7f8f5tsmm5mlk5oim359e-dk52k5uul50w49gbq4j1y7zzb 192.168.139.175:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

2、查看节点

# docker node ls
ID                           HOSTNAME      STATUS      AVAILABILITY   MANAGER STATUS
a1tno675d14sm6bqlc512vf10 *  swarm01        Ready         Active           Leader

3、查看加入集群manager管理节点的命令

# docker swarm join-token manager
To add a manager to this swarm, run the following command:
    docker swarm join --token SWMTKN-1-3sp9uxzokgr252u1jauoowv74930s7f8f5tsmm5mlk5oim359e-7tdlpdnkyfl1bnq34ftik9wxw 192.168.139.175:2377

4、查看加入集群worker节点的命令

# docker swarm join-token worker
To add a worker to this swarm, run the following command:
    docker swarm join --token SWMTKN-1-3sp9uxzokgr252u1jauoowv74930s7f8f5tsmm5mlk5oim359e-dk52k5uul50w49gbq4j1y7zzb 192.168.139.175:2377

5、将前面规划的两个worker节点加入集群

# docker swarm join --token SWMTKN-1-3sp9uxzokgr252u1jauoowv74930s7f8f5tsmm5mlk5oim359e-dk52k5uul50w49gbq4j1y7zzb 192.168.139.175:2377
This node joined a swarm as a worker.

6、查看worker节点是否已加入集群

# docker node ls
ID                        HOSTNAME    STATUS  AVAILABILITY  MANAGER STATUS
7zkbqgrjlsn8c09l3fagtfwre     swarm02  Ready      Active              
a1tno675d14sm6bqlc512vf10 *   swarm01  Ready      Active         Leader
apy9zys2ch4dlwbmgdqwc0pn3     swarm03  Ready      Active

7、查看docker swarm的管理网络

# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
05efca714d2f        bridge              bridge              local
c9cd9c37edd7        docker_gwbridge     bridge              local
10ac9e48d81b        host                host                local
n60tdenc5jy7        ingress             overlay             swarm
a9284277dc18        none                null                local

这里,一个docker swarm集群就搭建好了

四、搭建docker swarm的UI—Portainer

Portainer地址:https://portainer.io/。

1、使用该命令部署Portainer

# docker service create 
--name portainer 
--publish 9000:9000 
--constraint 'node.role == manager' 
--mount type=bind,src=//var/run/docker.sock,dst=/var/run/docker.sock 
portainer/portainer 
-H unix:///var/run/docker.sock
# docker images |grep portainer
portainer/portainer  latest  07cde96d4789   2 weeks ago  10.4MB
# docker service ls                    ###查看集群列表
ID              NAME        MODE     REPLICAS      IMAGE             PORTS
p5bo3n0fmqgz  portainer  replicated    1/1   portainer/portainer:latest   *:9000->9000/tcp

这就部署好了

2、浏览器输入http://localhost:9000进入该UI界面,如下所示,第一次进入Portainer,配置8位数的admin密码

未分类

密码修改完成后点击“validate”验证

未分类

如下图所示,输入admin用户名和密码进入Portainer

未分类

首页如下

未分类

查看swarm节点模块

未分类

这里可以在images模块pull镜像,在这里我pull了nginx

未分类

在Services模块下创建nginx服务,Services > Add service,这里创建三个副本,并将80端口映射出去,最后点击“Create Service”创建服务

未分类

刷新服务列表,查看是否创建成功

未分类

3、使用命令进行确认

# docker images | grep nginx
nginx   latest    b8efb18f159b     7 days ago     107MB
# ansible node -m shell -a 'docker images|grep nginx'
192.168.139.177 | SUCCESS | rc=0 >>
nginx   latest    b8efb18f159b     8 days ago     107MB
192.168.139.176 | SUCCESS | rc=0 >>
nginx   latest    b8efb18f159b     8 days ago     107MB
# docker service ls        ###查看服务的任务列表
ID             NAME     MODE     REPLICAS   IMAGE        PORTS
emrs3rj73bwh  Nginx  replicated   3/3    nginx:latest  *:80->80/tcp
p5bo3n0fmqgz  portainer  replicated  1/1  portainer/portainer:latest   *:9000->9000/tcp
# docker service ps Nginx  
ID                  NAME                IMAGE               NODE         
0smpndfx0bwc        Nginx.1             nginx:latest        swarm03      
werrrzlyfbf1        Nginx.2             nginx:latest        swarm01   
l7puro0787cj        Nginx.3             nginx:latest        swarm02 

DESIRED STATE       CURRENT STATE          ERROR               PORTS      
Running          Running 15 minutes ago                                   
Running          Running 15 minutes ago                                  
Running          Running 15 minutes ago

未分类

五、搭建docker swarm的UI—Shipyard

Shipyard的UI也是比较简单的,但是比较反复,它需要在每个节点都pull相应镜像才能加入Shipyard的UI。

1、先pull相应镜像到本地,这里我使用的是网易蜂巢的镜像,很快而且镜像也是比较新的

# docker pull hub.c.163.com/library/alpine:latest
# docker pull hub.c.163.com/library/rethinkdb:latest
# docker pull hub.c.163.com/longjuxu/microbox/etcd:latest
# docker pull hub.c.163.com/wangjiaen/shipyard/docker.io/shipyard/docker-proxy:latest
# docker pull hub.c.163.com/library/swarm:latest
# docker pull hub.c.163.com/wangjiaen/shipyard/docker.io/shipyard/shipyard:latest

2、给这些镜像新建一个tag标签

# docker tag 7328f6f8b418 alpine
# docker tag 4a511141860c rethinkdb
# docker tag 6aef84b9ec5a microbox/etcd 
# docker tag cfee14e5d6f2 shipyard/docker-proxy
# docker tag 0198d9ac25d1 swarm
# docker tag 36fb3dc0907d shipyard/shipyard

3、使用如下命令搭建Shipyard的UI

# curl -sSL https://shipyard-project.com/deploy | bash -s
Deploying Shipyard
 -> Starting Database
 -> Starting Discovery
 -> Starting Cert Volume
 -> Starting Proxy
 -> Starting Swarm Manager
 -> Starting Swarm Agent
 -> Starting Controller
Waiting for Shipyard on 192.168.139.175:8080
..
Shipyard available at http://192.168.139.175:8080
Username: admin Password: shipyard

4、根据提示输入http://localhost:8080,输入用户名admin,密码shipyard进入shipyard

未分类

5、进入shipyard首页容器界面

未分类

6、进入nodes模块查看,这里现在只有manager节点

未分类

7、在worker节点上pull并tag镜像,即是重复如上的第①和第②步,之后,在该worker节点上输入如下命令将其加入shipyard

# curl -sSL https://shipyard-project.com/deploy | ACTION=node DISCOVERY=etcd://192.168.139.175:4001 bash -s 
Adding Node
 -> Starting Cert Volume
 -> Starting Proxy
 -> Starting Swarm Manager
 -> Starting Swarm Agent
Node added to Swarm: 192.168.139.176

未分类

其他节点同理。

对比两种UI,其实都是比较简单的,个人认为Portainer较好,在manager节点pull一个镜像即可搭建UI。

问题:

  • manager:
# docker swarm init --advertise-addr 192.168.139.175
  • worker:
# docker swarm join --token SWMTKN-1-4dwtfbdvjmuf3limglbpy66k85ply2cn66hd0ugsaxfed5fj1d-3rp33pedt9k7ewpfizbzc9bvi 192.168.139.175:2377
Error response from daemon: Timeout was reached before node was joined. The attempt to join the swarm will continue in the background. Use the "docker info" command to see the current swarm status of your node.

出现worker节点无法加入集群的问题,这里需要设置监听地址全零。

使用docker-swarm创建docker高可用集群

Swarm概念

Swarm是Docker公司推出的用来管理docker集群,它将一群Docker宿主机变成一个单一的,虚拟的主机。Swarm使用标准的Docker API接口作为其前端访问入口,换言之,各种形式的Docker Client(docker client in Go, docker_py, docker等)均可以直接与Swarm通信。Swarm几乎全部用go语言来完成开发,Swarm0.2发布,相比0.1版本,0.2版本增加了一个新的策略来调度集群中的容器,使得在可用的节点上传播它们,以及支持更多的Docker命令以及集群驱动。
  
Swarm deamon只是一个调度器(Scheduler)加路由器(router),Swarm自己不运行容器,它只是接受docker客户端发送过来的请求,调度适合的节点来运行容器,这意味着,即使Swarm由于某些原因挂掉了,集群中的节点也会照常运行,当Swarm重新恢复运行之后,它会收集重建集群信息.

Swarm结构图

未分类

Swarm的基本命令

docker node 用来显示集群的节点,默认建立时只有一个节点,当然也就谈不上高可用了,可以使用docker node –help来查看所有node参数

未分类

集群初始化 docker swarm init

未分类

当已经被初始化后,就不能重新执行这个操作了,使用docker node ls 来查看刚建立的集群

集群中的管理节点和工作节点功能图

未分类

添加管理节点 docker swarm join

Docker Swarm 命令中还需要添加一些选项:

  • join:表明一个新的节点将被添加进 Swarm

  • –manager:表明节点的性质(manager vs worker)

  • –listen-addr:让一个新添加的节点可以访问 Swarm 内的其他节点

  • 最后的参数就是第一管理节点的地址(即这一命令将被送到的那个节点)

注意:由于 –auto-accept manager 选项会在 Swarm 初始化的过程中被提供,所以第二管理节点会被自动接受。如果没有这一选项,那么第二管理节点需要被第一管理节点手动接受。

$ MANAGER2_IP=$(docker-machine ip manager2)
docker-machine ssh manager2 docker swarm join --manager --listen-addr $MANAGER2_IP:2377 $MANAGER1_IP:2377

Swarn部署时使用的脚本,来自网络

下面是一小段用来创建 Docker 主机并部署 Swarm 的 Shell 脚本。当然了,管理/工作节点的数字都是可以随意改动的。
注意:创建两个管理节点和两个工作节点,仅仅是用来作示范。在工业生产中,我们可能需要在集群里搭建 3 个管理节点和 5 个工作节点。

# Define the number of managers/workers
MANAGER=3
WORKER=5

# Create the Docker hosts
for i in $(seq 1 $MANAGER); do docker-machine create --driver virtualbox manager$i; done
for i in $(seq 1 $WORKER); do docker-machine create --driver virtualbox worker$i; done

# Init the swarm
docker-machine ssh manager1 docker swarm init --auto-accept manager --auto-accept worker --listen-addr $(docker-machine ip manager1):2377

# Add additional manager(s)
for i in $(seq 2 $MANAGER); do docker-machine ssh manager$i docker swarm join --manager --listen-addr $(docker-machine ip manager$i):2377 $(docker-machine ip manager1):2377; done

# Add workers
for i in $(seq 1 $WORKER); do docker-machine ssh worker$i docker swarm join --listen-addr $(docker-machine ip worker$i):2377 $(docker-machine ip manager1):2377; done

对于上面文章中,只提到了集群,而没有谈到如何去使用,在建立集群后,服务的部署我们可以用

docker stack deploy  -c test.yml test

下面给出自己写的一个服务,版本3的

version: "3"

services:
  loggerapi:
    image: logger.api
    build:
      context: ./src/Logger.Api
      dockerfile: Dockerfile
    ports:
      - "5000:80"
    networks:
      - ingress

 loggermanager:
    image: logger.manager
    build:
      context: ./src/Logger.Manager
      dockerfile: Dockerfile
    ports:
      - "5050:80"
    networks:
      - ingress

networks:
  ingress:

这里有个服务要注意,服务的名称一定不能有点,如logger.manager这是错误的!

未分类

来建立一个服务,同时可以使用docker service来查看已经运行的服务!

还有一点要注意,yml在进行v3版后,不再支持build,也就是说,你需要先把镜像建立好才行!

未分类

使用Jenkins Ansible Docker Swarm实现自动化编译部署

自动化部署在项目部署过程中很重要,一旦自动化部署完成,我们就可以减轻我们手动的操作的步骤以及出错的概率。下面介绍一种通用的自动化部署。从打包编译到上线,一条命令就完成所有操作。简单而高效

1、Jenkins部署这里不在赘述,直接从新建项目开始。

项目截图,如下:增加两个变量如图,

  • BranchTobuild 默认是master分支,在编译的时候也可以指定分支。

  • PushDockerImage 默认布尔值是选中,直接把镜像推到镜像仓库。

未分类

增加Pipeline配置,主要是分了几个步骤。所以用pipeline,也可以不用这种方式,直接脚本也行

所有执行步骤写入Jenkinsfile中,并把文件放入项目的根目录,这样才能调用。

未分类

Jenkinsfile内容如下:包括编译、打包、推送docker镜像到仓库,ansible部署。

#cat Jenkinsfile
pipeline {

   //定义了执行jenkins的机器
    agent {
        label ‘master’
    }
    stages {
        stage (‘Prepare’) {
            steps {
                sh “echo Prepare”
                //准备阶段,没有暂不处理
            }
        }

        //build打包过程,最后会生产apk包
        stage (‘build’) {
            steps {
                sh ‘echo “start Build”‘
                script {
                    if (params.buildDebug) {
                        sh ‘echo “build debug version”‘
                        sh ‘chmod +x ./gradlew’
                        sh “./gradlew clean”
                        sh “./gradlew build –debug”
                    } else {
                        sh ‘echo “build release version”‘
                        sh ‘chmod +x ./gradlew’
                        sh “./gradlew clean”
                        sh “./gradlew build”
                    }
                }
            }
        }
        stage (‘Test’) {
            steps {
                sh “echo Test”
                //测试阶段,没有暂不处理
            }
        }

       //发布阶段,项目中包括了gradle.properties文件,几个变量:版本、项目、产品,按照这几个名词生产镜像的名
        stage (‘Deploy’) {
            steps {
                sh ‘echo “Start Docker Build And Push Images”‘
                script {
                    if (params.PushDockerImage) {
                        def props = readProperties  file: ‘gradle.properties’
                                    def VERSION = props[‘version’]
                                    def PRODUCT = props[‘product’]
                                    def ARTIFACT = props[‘artifact’]
                        sh ‘echo “start Build”‘
                                    //开始修改Dockerfile
                                    sh “sed -i ‘s#${PRODUCT}#${PRODUCT}#g’ Dockerfile”
                                    sh “sed -i ‘s#${VERSION}#${VERSION}#g’ Dockerfile”
                                    sh “sed -i ‘s#${ARTIFACT}#${ARTIFACT}#g’ Dockerfile”
                        sh “docker build -t registry.sreop.com:5000/${PRODUCT}/${ARTIFACT}:${VERSION} -f Dockerfile .”
                        sh ‘echo “Publish Images To registry.leautolink.com”‘
                        sh “docker push registry.leautolink.com:5000/${PRODUCT}/${ARTIFACT}:${VERSION}”

                        //ansible playbook 部署到线上或者测试环境
                        sh “sudo /usr/bin/ansible-playbook  /data/base-docker-compose/product/light/prod/playbook.yml”
                    }
                }
            }
        }
    }
}

2、每个项目需要一个Dockefile

cat Dockerfile
# 基础镜像
FROM registry.sreop.com:5000/alpine-java:8u121b13_jdk_unlimited
# 维护者信息
MAINTAINER [email protected]
# 镜像操作命令
RUN mkdir -p /data/bin/${PRODUCT}/${ARTIFACT}
# 指定后续命令的执行目录
WORKDIR /data/bin/${PRODUCT}/${ARTIFACT}
# 对外连接端口号
EXPOSE 12429
# 向镜像中增加文件
ADD ./build/libs/${ARTIFACT}-${VERSION}.jar .
# 容器启动命令
CMD java -Djava.security.egd=file:/dev/./urandom -jar ${ARTIFACT}-${VERSION}.jar –spring.profiles.active=prod

3、写ansible playbook,为推送到Docker集群平台,并部署到线上或者测试平台。

注意:docker-compose.yml要拷贝到每个docker节点机器上。功能是:获取各个变量,拉取镜像。最后生产docker services

– name: light Pull Image
  hosts: docker-swarm-prod
  remote_user: root
  tasks:
    – name: get product var 
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml |head -n1|awk -F’/’ ‘{print $2}’
      register: product
    – name: get artifact var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1 |awk -F’/’ ‘{print $3}’|sed ‘s#(.*):(.*)#1#g’
      register: artifact
    – name: get version var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1 |awk -F’/’ ‘{print $3}’|sed ‘s#(.*):(.*)#2#g’
      register: version
    – name: docker pull image
      shell: docker pull registry.leautolink.com:5000/”{{ product.stdout }}”/”{{ artifact.stdout }}”:”{{ version.stdout }}” || /bin/true

– name: Remove Docker Old Verison
  hosts: docker-swarm-prod-lead 
  remote_user: root
  tasks:
    – name: get product var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1|awk -F’/’ ‘{print $2}’
      register: product
    – name: get artifact var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1 |awk -F’/’ ‘{print $3}’|sed ‘s#(.*):(.*)#1#g’
      register: artifact
    – name: get version var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1 |awk -F’/’ ‘{print $3}’|sed ‘s#(.*):(.*)#2#g’
      register: version
    – name: remove light
      shell: docker stack rm {{ artifact.stdout }} || /bin/true

– name: Start New verison
  hosts: docker-swarm-prod-lead 
  remote_user: root
  tasks:
    – name: get product var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1|awk -F’/’ ‘{print $2}’
      register: product
    – name: get artifact var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1 |awk -F’/’ ‘{print $3}’|sed ‘s#(.*):(.*)#1#g’
      register: artifact
    – name: get version var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1 |awk -F’/’ ‘{print $3}’|sed ‘s#(.*):(.*)#2#g’
      register: version
    – name: start light
      shell: docker stack deploy -c /data/base-docker-compose/product/light/prod/docker-compose.yml {{ artifact.stdout }} || /bin/true 

4、swarm集群部署compose.yml

# cat docker-compose.yml 
version: “3”
services:
  config-server:
    image: registry.sreop.com:5000/leradio/light:1.0.1-RELEASE
    command: java -Djava.security.egd=file:/dev/./urandom -jar light-1.0.1-RELEASE.jar –spring.cloud.config.profile=prod –spring.profiles.active=prod
    ports:
      – 12429:12429
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
      restart_policy:
        condition: on-failure
networks:
  frontend:

初步体验docker swarm集群

之前用的阿里云容器服务,但由于acsrouting的路由错乱问题,被逼上自建docker swarm的梁山。今天尝试自己搭建docker swarm,竟然轻松搞定,简单的超乎想象。

以下是实际搭建操作步骤:

1、创建集群

# docker swarm init --advertise-addr 10.251.242.231
Swarm initialized: current node (m9dfl7r9wo1e9jxsp3oe5du3x) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token xxx 10.251.242.231:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

主:10.251.242.231 是 docker 主机的内网IP地址

2、docker info 查看刚刚创建的集群信息

Swarm: active
 NodeID: m9dfl7r9wo1e9jxsp3oe5du3x
 Is Manager: true
 ClusterID: j01wzizw7gy0ck95p1d7a4pmv
 Managers: 1
 Nodes: 1
 Orchestration:
  Task History Retention Limit: 5

3、docker node ls 查看节点信息

ID                            HOSTNAME               STATUS              AVAILABILITY        MANAGER STATUS
m9dfl7r9wo1e9jxsp3oe5du3t *   swarm-websites-node1   Ready               Active              Leader

4、创建用于部署应用容器的网络

# docker network create --driver=overlay --attachable cnblogs

5、创建用于部署Docker Flow Proxy容器的网络(Docker Flow Proxy支持根据主机名将请求转发至对应的应用容器)

docker network create --driver overlay proxy

6、查看刚刚创建的网络

# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
rl96kcw8ytpa        cnblogs             overlay             swarm
61kbxtvnivkx        proxy               overlay             swarm

7、部署 Docker Flow Proxy stack

7.1 下载 docker-compose-stack.yml 文件

# curl -o docker-compose-stack.yml 
    https://raw.githubusercontent.com/
vfarcic/docker-flow-proxy/master/docker-compose-stack.yml

7.2 部署 stack

# docker stack deploy -c docker-compose-stack.yml proxy

8、编写示例应用 openapi 的 docker-compose-stack.yml

version: '3.2'
services:
  api:
    image: open-api:latest
    deploy:
      replicas: 2
      update_config:
        delay: 5s
      labels:
        - com.df.notify=true
        - com.df.distribute=true
        - com.df.serviceDomain=api.cnblogs.com
        - com.df.port=80
    networks:
      - cnblogs
      - proxy
networks:
  cnblogs:
    external: true
  proxy:
    external: true

9、部署示例应用的 stack

docker stack deploy -c docker-compose-stack.yml openapi

10、部署完成后可以通过 http://api.cnblogs.com 访问运行在 openapi_api service 中的站点

11、添加机器进集群作为节点

docker swarm join --token xxxxxxxxx IP:2377

12、将节点提升为manager

docker node promote ID或HOSTNAME