Docker自学笔记(三)

Docker 网络

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fZzs1BHX-1653915420756)(…/…/图片/typora/111111111111111.jpg)]

veth-pair 就是一对的虚拟设备接口,和 tap/tun 设备不同的是,它都是成对出现的。一端连着协议栈,一端彼此相连着。

[root@testhost ~]# ip ad
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:bc:54:3c brd ff:ff:ff:ff:ff:ff
    inet 192.168.8.104/24 brd 192.168.8.255 scope global dynamic noprefixroute ens33
       valid_lft 48185sec preferred_lft 48185sec
    inet6 fd20:da22:32d4:1e00:cda:9261:c8ac:4855/64 scope global dynamic noprefixroute
       valid_lft 7038sec preferred_lft 3438sec
    inet6 fe80::1370:ec5d:2644:b710/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:2b:64:5d:db brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:2bff:fe64:5ddb/64 scope link
       valid_lft forever preferred_lft forever
5: vethd2aa05f@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether 2e:35:ae:bf:c5:d3 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::2c35:aeff:febf:c5d3/64 scope link
       valid_lft forever preferred_lft forever
13: veth80149d4@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether 5e:4e:de:5c:2c:07 brd ff:ff:ff:ff:ff:ff link-netnsid 2
    inet6 fe80::5c4e:deff:fe5c:2c07/64 scope link
       valid_lft forever preferred_lft forever

– link

在本机添加对应的A记录


[root@testhost ~]# docker exec -it tomcat01 ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.107 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.059 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.078 ms
64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.067 ms
64 bytes from 172.17.0.3: icmp_seq=5 ttl=64 time=0.045 ms
64 bytes from 172.17.0.3: icmp_seq=6 ttl=64 time=0.065 ms
^C
--- 172.17.0.3 ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5125ms
rtt min/avg/max/mdev = 0.045/0.070/0.107/0.019 ms
[root@testhost ~]# docker exec -it tomcat01 ping lxftomcat
ping: lxftomcat: Name or service not known
[root@testhost ~]# docker run -d -P --name tomcat02 --link lxftomcat diytomcat
ee6667300af7d609b21f824f9f9f39fca0bfb0f27c0c9dccf11e351c06072eb6
[root@testhost ~]# docker exec -it tomcat02 ping lxftomcat
PING lxftomcat (172.17.0.3) 56(84) bytes of data.
64 bytes from lxftomcat (172.17.0.3): icmp_seq=1 ttl=64 time=0.131 ms
64 bytes from lxftomcat (172.17.0.3): icmp_seq=2 ttl=64 time=0.050 ms
64 bytes from lxftomcat (172.17.0.3): icmp_seq=3 ttl=64 time=0.044 ms
64 bytes from lxftomcat (172.17.0.3): icmp_seq=4 ttl=64 time=0.045 ms
^C
--- lxftomcat ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3091ms
rtt min/avg/max/mdev = 0.044/0.067/0.131/0.037 ms
[root@testhost ~]# docker inspect ee6667300af7 | cat -n | grep lxf

    63                  "/lxftomcat:/tomcat02/lxftomcat"
    
[root@testhost ~]# docker exec -it tomcat02 cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3      lxftomcat 497652168d31
172.17.0.5      ee6667300af7
[root@testhost ~]#

自定义网络

查看所有网络

[root@testhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
b04fa2d26754   bridge    bridge    local  # 桥接模式
f749e9fa8a2c   host      host      local  # 主机模式
e6f409cc717e   none      null      local  # 不配置网络
			caotainers                     # 容器互联网络
			
			
# docker run -d -P --name tomcat01 --net brige diytomcat  默认参数--net brige



[root@testhost ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
53395142c4a8ff9e26df1de752c920f8db36c842a22eca3de3df140cf2d75046
[root@testhost ~]# docker  network ls
NETWORK ID     NAME      DRIVER    SCOPE
b04fa2d26754   bridge    bridge    local
f749e9fa8a2c   host      host      local
53395142c4a8   mynet     bridge    local
e6f409cc717e   none      null      local

[root@testhost ~]# docker network inspect 53395142c4a8
[
    {
        "Name": "mynet",
        "Id": "53395142c4a8ff9e26df1de752c920f8db36c842a22eca3de3df140cf2d75046",
        "Created": "2022-05-29T07:17:03.251644161+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
[root@testhost ~]#ip add 
20: br-53395142c4a8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:39:7f:49:4e brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.1/16 brd 192.168.255.255 scope global br-53395142c4a8
       valid_lft forever preferred_lft forever
    inet6 fe80::42:39ff:fe7f:494e/64 scope link
       valid_lft forever preferred_lft forever

使用自己网络可以支持 ping 容器名称

[root@testhost ~]# docker run -d -P --name tomcat01 --net mynet diytomcat
cce9e9c7664a0e405f832967cd7957dffb1036b9fd12aa8bf34ce77ae1d89d2f
[root@testhost ~]# docker run -d -P --name tomcat02 --net mynet diytomcat
9ff4b8d9669d5c80ac482651b969b034fe3bcc78be771d274589829c73924a01


root@testhost ~]# docker exec -it tomcat01 ping tomcat02
PING tomcat02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.068 ms
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.105 ms
^C
--- tomcat02 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1052ms
rtt min/avg/max/mdev = 0.068/0.086/0.105/0.020 ms
[root@testhost ~]# ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.062 ms
^C
--- 192.168.0.3 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.062/0.062/0.062/0.000 ms
[root@testhost ~]# ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.062 ms
^C
--- 192.168.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.062/0.062/0.062/0.000 ms
[root@testhost ~]#

docker 网络联通

# docker network  connect mynet lxftomcat

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sVXAEKHB-1653915420757)(…/…/图片/typora/1653751671852.png)]

练习 Redis 集群部署

for port in $(seq 1 6)
do \ 
mkdir -p /root/redis/node-${port}/conf
touch  /root/redis/node-${port}/conf/redis.conf
cat <<EOF>>  /root/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done


docker run -p 6471:6379 -p 16371:16379 --name redis-1 -v /root/redis/node-1/data:/data -v /root/redis/node-1/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6472:6379 -p 16372:16379 --name redis-2 -v /root/redis/node-2/data:/data -v /root/redis/node-2/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6473:6379 -p 16373:16379 --name redis-3 -v /root/redis/node-3/data:/data -v /root/redis/node-3/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6474:6379 -p 16374:16379 --name redis-4 -v /root/redis/node-4/data:/data -v /root/redis/node-4/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6475:6379 -p 16375:16379 --name redis-5 -v /root/redis/node-5/data:/data -v /root/redis/node-5/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6476:6379 -p 16376:16379 --name redis-6 -v /root/redis/node-6/data:/data -v /root/redis/node-6/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf


docker exec -it redis-1 /bin/sh

 redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
 
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.38.0.15:6379 to 172.38.0.11:6379
Adding replica 172.38.0.16:6379 to 172.38.0.12:6379
Adding replica 172.38.0.14:6379 to 172.38.0.13:6379
M: adc7a4b756a86c0e14c52e68ddc80355654dc073 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
M: 2258330dac90eb5324963bbeb5a6ab33579584cc 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
M: 9904a350bd3b35ffeaa1de3a3ff7051569c25ff8 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
S: dfc4412e495e1ec6c37fe71e003e4a49976d80ac 172.38.0.14:6379
   replicates 9904a350bd3b35ffeaa1de3a3ff7051569c25ff8
S: 8fc9bad38b81bf4831650b93275869ee28e2e5a2 172.38.0.15:6379
   replicates adc7a4b756a86c0e14c52e68ddc80355654dc073
S: ea3071f1260e9af6212fe274e698da64e6b636af 172.38.0.16:6379
   replicates 2258330dac90eb5324963bbeb5a6ab33579584cc
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
....
>>> Performing Cluster Check (using node 172.38.0.11:6379)
M: adc7a4b756a86c0e14c52e68ddc80355654dc073 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 8fc9bad38b81bf4831650b93275869ee28e2e5a2 172.38.0.15:6379
   slots: (0 slots) slave
   replicates adc7a4b756a86c0e14c52e68ddc80355654dc073
S: ea3071f1260e9af6212fe274e698da64e6b636af 172.38.0.16:6379
   slots: (0 slots) slave
   replicates 2258330dac90eb5324963bbeb5a6ab33579584cc
S: dfc4412e495e1ec6c37fe71e003e4a49976d80ac 172.38.0.14:6379
   slots: (0 slots) slave
   replicates 9904a350bd3b35ffeaa1de3a3ff7051569c25ff8
M: 9904a350bd3b35ffeaa1de3a3ff7051569c25ff8 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
M: 2258330dac90eb5324963bbeb5a6ab33579584cc 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

/data # redis-cli -c
127.0.0.1:6379> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:62
cluster_stats_messages_pong_sent:64
cluster_stats_messages_sent:126
cluster_stats_messages_ping_received:59
cluster_stats_messages_pong_received:62
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:126
127.0.0.1:6379> cluster nodes
adc7a4b756a86c0e14c52e68ddc80355654dc073 172.38.0.11:6379@16379 myself,master - 0 1653783937000 1 connected 0-5460
8fc9bad38b81bf4831650b93275869ee28e2e5a2 172.38.0.15:6379@16379 slave adc7a4b756a86c0e14c52e68ddc80355654dc073 0 1653783938000 5 connected
ea3071f1260e9af6212fe274e698da64e6b636af 172.38.0.16:6379@16379 slave 2258330dac90eb5324963bbeb5a6ab33579584cc 0 1653783937500 6 connected
dfc4412e495e1ec6c37fe71e003e4a49976d80ac 172.38.0.14:6379@16379 slave 9904a350bd3b35ffeaa1de3a3ff7051569c25ff8 0 1653783937000 4 connected
9904a350bd3b35ffeaa1de3a3ff7051569c25ff8 172.38.0.13:6379@16379 master - 0 1653783938513 3 connected 10923-16383
2258330dac90eb5324963bbeb5a6ab33579584cc 172.38.0.12:6379@16379 master - 0 1653783937000 2 connected 5461-10922
127.0.0.1:6379>


127.0.0.1:6379> set a b
-> Redirected to slot [15495] located at 172.38.0.13:6379
OK
172.38.0.13:6379> get  a
^C
/data # redis-cli -c
127.0.0.1:6379> get  a
-> Redirected to slot [15495] located at 172.38.0.14:6379
"b"
172.38.0.14:6379>



172.38.0.14:6379> cluster nodes
9904a350bd3b35ffeaa1de3a3ff7051569c25ff8 172.38.0.13:6379@16379 master,fail - 1653784002739 1653784002536 3 connected
2258330dac90eb5324963bbeb5a6ab33579584cc 172.38.0.12:6379@16379 master - 0 1653784064586 2 connected 5461-10922
8fc9bad38b81bf4831650b93275869ee28e2e5a2 172.38.0.15:6379@16379 slave adc7a4b756a86c0e14c52e68ddc80355654dc073 0 1653784064995 5 connected
ea3071f1260e9af6212fe274e698da64e6b636af 172.38.0.16:6379@16379 slave 2258330dac90eb5324963bbeb5a6ab33579584cc 0 1653784064000 6 connected
dfc4412e495e1ec6c37fe71e003e4a49976d80ac 172.38.0.14:6379@16379 myself,master - 0 1653784063000 7 connected 10923-16383
adc7a4b756a86c0e14c52e68ddc80355654dc073 172.38.0.11:6379@16379 master - 0 1653784065503 1 connected 0-5460
172.38.0.14:6379>




Docker Compose

Docker Compose |概述Docker 文档

简介

Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。

Compose 使用的三个步骤:

  • 使用 Dockerfile 定义应用程序的环境。
  • 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。
  • 最后,执行 docker-compose up 命令来启动并运行整个应用程序。

作用:批量容器编排

安装

先决条件

Docker Compose 依靠 Docker Engine 进行任何有意义的工作,因此请确保在本地或远程安装了 Docker 引擎,具体取决于您的设置。

  • 在桌面系统上,如Docker Desktop for Mac和Windows,Docker Compose作为这些桌面安装的一部分包含在内。
  • 在 Linux 系统上,您可以使用方便脚本使用 Docker 引擎安装 Docker Compose。为您的发行版选择安装 Docker 引擎页面,然后查找有关使用方便脚本进行安装的说明。
    否则,您应该首先为您的操作系统安装 Docker 引擎,然后参阅此页面以获取有关在 Linux 系统上安装 Compose 的说明。
  • 要以非 root 用户身份运行 Compose,请参阅以非 root 用户身份管理 Docker

安装撰写

按照以下说明在 Mac、Windows、Windows Server 或 Linux 系统上安装 Compose。

安装其他版本

以下说明概述了 Compose 当前稳定版本 (v2.5.0) 的安装。若要安装其他版本的 Compose,请将给定的版本号替换为所需的版本号。

还会在 GitHub 上的撰写存储库版本页面上列出并直接下载撰写版本。

若要安装 Python 版本的 Compose,请按照 Compose v1 GitHub 分支中的说明进行操作。

  • 苹果电脑

  • 窗户

  • 视窗服务器

  • Linux

  • Linux 独立二进制文件

在 Linux 系统上安装 Compose

您可以根据需要以不同的方式安装 Docker Compose:

使用便利脚本进行安装

由于 Docker Compose 现在是 Docker CLI 的一部分,因此可以通过带有 Docker 引擎和 CLI 的便利脚本进行安装。
选择您的 Linux 发行版,然后按照说明进行操作。

使用存储库安装

如果您已经按照说明安装 Docker 引擎,则应该已经安装了 Docker Compose。
否则,您可以按照 Docker 引擎安装中提到的方式设置 Docker 存储库,选择您的 Linux 发行版并转到该部分。Set up the repository

完成后

  1. 更新包索引,并安装最新版本的 Docker Compose,或转到下一步以安装特定版本:apt

     $ sudo apt-get update
     $ sudo apt-get install docker-compose-plugin
    
  2. 要安装特定版本的 Docker 引擎,请在存储库中列出可用版本,然后选择并安装:

    一个。列出存储库中可用的版本:

    $ apt-cache madison docker-compose-plugin
    
      docker-compose-plugin | 2.3.3~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable arm64 Packages
    

    b.使用第二列中的版本字符串安装特定版本,例如 。2.3.3~ubuntu-focal

    $ sudo apt-get install docker-compose-plugin=<VERSION_STRING>
    
  3. 通过检查版本来验证 Docker Compose 是否已正确安装。

    $ docker compose version
    Docker Compose version v2.3.3
    
手动安装二进制文件

在 Linux 上,您可以从 GitHub 上的 Compose 存储库发布页面下载 Docker Compose 二进制文件,并将其复制为 。按照链接中的说明进行操作,这涉及在终端中运行命令以下载二进制文件。下面还包括这些分步说明。$HOME/.docker/cli-plugins``docker-compose``curl

  1. 运行以下命令以下载 Docker Compose 的当前稳定版本:

    $ DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
    $ mkdir -p $DOCKER_CONFIG/cli-plugins
    $ curl -SL https://get.daocloud.io/docker/compose/releases/download/v2.5.0/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x56xl8Eu-1653915420757)(…/…/图片/typora/1653792936026.png)]

    此命令在目录下为活动用户安装撰写。要为系统上的所有用户安装 Docker Compose,请将 替换为 。$HOME``~/.docker/cli-plugins``/usr/local/lib/docker/cli-plugins

    若要安装其他版本的 Compose,请使用要使用的 Compose 版本进行替换。v2.5.0

  2. 将可执行权限应用于二进制文件:

     $ chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
    

    或者,如果您选择为所有用户安装撰写

     $ sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
    
  3. 测试安装。

     $ docker compose version
     Docker Compose version v2.5.0
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1e9zwiUl-1653915420758)(…/…/图片/typora/1653793029364.png)]

卸载

要卸载 Docker Compose(如果您使用 以下工具安装):curl

$ rm $DOCKER_CONFIG/cli-plugins/docker-compose

或者,如果您选择为所有用户安装撰写

$ sudo rm /usr/local/lib/docker/cli-plugins/docker-compose

出现“权限被拒绝”错误?

如果您在使用上述任一方法时收到“权限被拒绝”错误,则您可能没有删除 的适当权限。要强制删除,请先附加上述任一命令,然后再次运行。docker-compose``sudo

体验

  1. 应用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 'Hello World! I have been seen {} times.\n'.format(count)
    
  2. dockerfile 应用打包成镜像

    # syntax=docker/dockerfile:1
    FROM python:3.7-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"]
    
    
  3. docker compose yml 文件

    
    version: "3.9"
    services:
      web:
        build: .
        ports:
          - "8000:5000"
      redis:
        image: "redis:alpine"
    
    
  4. 启动compose 项目

流程:

  1. 创建网络
  2. 执行Docker compose yaml
  3. 启动服务
[root@testhost composetest]# docker compose up
[+] Running 7/7
 ⠿ redis Pulled                                                                                                19.7s
   ⠿ 59bf1c3509f3 Pull complete                                                                                 5.8s
   ⠿ 719adce26c52 Pull complete                                                                                 6.0s
   ⠿ b8f35e378c31 Pull complete                                                                                 6.9s
   ⠿ d034517f789c Pull complete                                                                                 8.2s
   ⠿ 3772d4d76753 Pull complete                                                                                 8.3s
   ⠿ 211a7f52febb Pull complete                                                                                 8.4s
[+] Building 462.1s (15/15) FINISHED
 => [internal] load build definition from Dockerfile                                                            0.0s
 => => transferring dockerfile: 320B                                                                            0.0s
 => [internal] load .dockerignore                                                                               0.0s
 => => transferring context: 2B                                                                                 0.0s
 => resolve image config for docker.io/docker/dockerfile:1                                                     17.9s
 => docker-image://docker.io/docker/dockerfile:1@sha256:42399d4635eddd7a9b8a24be879d2f9a930d0ed040a61324cfdf59  2.1s
 => => resolve docker.io/docker/dockerfile:1@sha256:42399d4635eddd7a9b8a24be879d2f9a930d0ed040a61324cfdf59ef13  0.0s
 => => sha256:42399d4635eddd7a9b8a24be879d2f9a930d0ed040a61324cfdf59ef1357b3b2 2.00kB / 2.00kB                  0.0s
 => => sha256:93f32bd6dd9004897fed4703191f48924975081860667932a4df35ba567d7426 528B / 528B                      0.0s
 => => sha256:e532695ddd93ca7c85a816c67afdb352e91052fab7ac19a675088f80915779a7 1.21kB / 1.21kB                  0.0s
 => => sha256:24a639a53085eb680e1d11618ac62f3977a3926fedf5b8471ace519b8c778030 9.67MB / 9.67MB                  1.3s
 => => extracting sha256:24a639a53085eb680e1d11618ac62f3977a3926fedf5b8471ace519b8c778030                       0.7s
 => [internal] load .dockerignore                                                                               0.0s
 => [internal] load build definition from Dockerfile                                                            0.0s
 => [internal] load metadata for docker.io/library/python:3.7-alpine                                           20.0s
 => [1/6] FROM docker.io/library/python:3.7-alpine@sha256:d64e0124674d64e78cc9d7378a1130499ced66a7a00db0521d01  4.1s
 => => resolve docker.io/library/python:3.7-alpine@sha256:d64e0124674d64e78cc9d7378a1130499ced66a7a00db0521d01  0.0s
 => => sha256:a1034fd13493569ef2975c7c8c3bdd8aecee43aa2a9f102a24380b9cb724535b 8.10kB / 8.10kB                  0.0s
 => => sha256:8786870f287676cca49c1e1e5029467c087ad293b824fcddc489cbe2819745b2 282.15kB / 282.15kB              0.7s
 => => sha256:45d4696938d0cf96f85ae2d9a8eb8c0bb018e07b0f2a820c3118a7cb54e4dad8 10.55MB / 10.55MB                1.8s
 => => sha256:ef84af58b2c5560afbdd9265a475c59fe10c72032153ab8a79e77b961985c580 230B / 230B                      0.3s
 => => sha256:d64e0124674d64e78cc9d7378a1130499ced66a7a00db0521d0120a2e88ac9e4 1.65kB / 1.65kB                  0.0s
 => => sha256:98bdc8dd3aa5157f990a13a9cb58d4f9b8d089ae825c0d85b9d68e0c5f1918bd 1.37kB / 1.37kB                  0.0s
 => => sha256:c3c9b71b9a6957b500a5a45f5608c0099a8e7c9ba0714701cd041198d95b319b 2.35MB / 2.35MB                  1.7s
 => => extracting sha256:8786870f287676cca49c1e1e5029467c087ad293b824fcddc489cbe2819745b2                       0.2s
 => => extracting sha256:45d4696938d0cf96f85ae2d9a8eb8c0bb018e07b0f2a820c3118a7cb54e4dad8                       1.7s
 => => extracting sha256:ef84af58b2c5560afbdd9265a475c59fe10c72032153ab8a79e77b961985c580                       0.0s
 => => extracting sha256:c3c9b71b9a6957b500a5a45f5608c0099a8e7c9ba0714701cd041198d95b319b                       0.4s
 => [internal] load build context                                                                               0.0s
 => => transferring context: 1.09kB                                                                             0.0s
 => [2/6] WORKDIR /code                                                                                         0.3s
 => [3/6] RUN apk add --no-cache gcc musl-dev linux-headers                                                   396.5s
 => [4/6] COPY requirements.txt requirements.txt                                                                0.1s
 => [5/6] RUN pip install -r requirements.txt                                                                  19.7s
 => [6/6] COPY . .                                                                                              0.1s
 => exporting to image                                                                                          1.1s
 => => exporting layers                                                                                         1.1s
 => => writing image sha256:1cb2591260901eaa54b43729cdbc7f096d5ae66e4bcb39e478c36bc7d90fcfc1                    0.0s
 => => naming to docker.io/library/composetest_web                                                              0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
[+] Running 3/3
 ⠿ Network composetest_default    Created                                                                       0.2s
 ⠿ Container composetest-redis-1  Created                                                                       0.1s
 ⠿ Container composetest-web-1    Created                                                                       0.1s
Attaching to composetest-redis-1, composetest-web-1
composetest-redis-1  | 1:C 29 May 2022 11:15:48.727 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
composetest-redis-1  | 1:C 29 May 2022 11:15:48.727 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=1, just started
composetest-redis-1  | 1:C 29 May 2022 11:15:48.727 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
composetest-redis-1  | 1:M 29 May 2022 11:15:48.732 * monotonic clock: POSIX clock_gettime
composetest-redis-1  | 1:M 29 May 2022 11:15:48.733 * Running mode=standalone, port=6379.
composetest-redis-1  | 1:M 29 May 2022 11:15:48.733 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
composetest-redis-1  | 1:M 29 May 2022 11:15:48.733 # Server initialized
composetest-redis-1  | 1:M 29 May 2022 11:15:48.733 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
composetest-redis-1  | 1:M 29 May 2022 11:15:48.733 * Ready to accept connections
composetest-web-1    |  * Serving Flask app 'app.py' (lazy loading)
composetest-web-1    |  * Environment: production
composetest-web-1    |    WARNING: This is a development server. Do not use it in a production deployment.
composetest-web-1    |    Use a production WSGI server instead.
composetest-web-1    |  * Debug mode: off
composetest-web-1    |  * Running on all addresses (0.0.0.0)
composetest-web-1    |    WARNING: This is a development server. Do not use it in a production deployment.
composetest-web-1    |  * Running on http://127.0.0.1:5000
composetest-web-1    |  * Running on http://172.18.0.2:5000 (Press CTRL+C to quit)
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:16:54] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:16:54] "GET /favicon.ico HTTP/1.1" 404 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:17:38] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:17:39] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:17:39] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:17:40] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:17:40] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:17:41] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:17:41] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:17:42] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:17:42] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:17:42] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:17:43] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:17:43] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:17:43] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:17:43] "GET / HTTP/1.1" 200 -
composetest-web-1    | 172.18.0.1 - - [29/May/2022 11:17:43] "GET / HTTP/1.1" 200 -

停止服务 ctrl c

在项目目录下 dockers compose down

^CGracefully stopping... (press Ctrl+C again to force)
[+] Running 2/2
 ⠿ Container composetest-web-1    Stopped                                                                      10.3s
 ⠿ Container composetest-redis-1  Stopped                                                                       0.2s
canceled
[root@testhost composetest]#

yaml文件

https://docs.docker.com/compose/compose-file/

下面的示例阐释了使用具体示例应用程序编写规范概念。该样本是非规范性的。

services:
  frontend:
    image: awesome/webapp
    build: ./webapp

  backend:
    image: awesome/database
    build:
      context: backend
      dockerfile: ../backend.Dockerfile

  custom:
    build: ~/custom

当用于从源构建服务映像时,这样的 Compose 文件将创建三个 docker 映像:

  • awesome/webappdocker 映像是使用 Compose 文件父文件夹中的子目录作为 docker 构建上下文构建的。此文件夹中缺少 a 将引发错误。webapp``Dockerfile
  • awesome/databasedocker 映像是使用 Compose 文件父文件夹中的子目录构建的。 file 用于定义构建步骤,此文件是相对于上下文路径搜索的,这意味着对于此示例,将解析为 Compose 文件父文件夹,因此是同级文件。backend``backend.Dockerfile``..``backend.Dockerfile
  • Docker 映像是使用用户 HOME 中的目录作为 docker 上下文构建的。撰写实现警告用户用于构建映像的非可移植路径。custom

在推送时,两个和 Docker 映像都将推送到(默认)注册表。 将跳过服务映像,因为未设置任何属性,并且会警告用户此缺少的属性。awesome/webapp``awesome/database``custom``Image

生成定义

该元素定义 Compose 实现应用于从源构建 Docker 映像的配置选项。 可以指定为包含构建上下文路径的字符串或详细结构:build``build

services:
  webapp:
    build: ./dir

使用此字符串语法,只能将生成上下文配置为 Compose 文件父文件夹的相对路径。此路径必须是目录并包含 .Dockerfile

或者,可以是具有以下定义字段的对象build

上下文(必填)

context定义指向包含 Dockerfile 的目录的路径,或指向 git 存储库的 url。

当提供的值是相对路径时,必须将其解释为相对于 Compose 文件的位置。Compose 实现必须警告用户用于定义构建上下文的绝对路径,因为这些路径会阻止 Compose 文件可移植。

build:
  context: ./dir

dockerfile

dockerfile允许设置备用 Dockerfile。必须从生成上下文解析相对路径。撰写实现必须警告用户用于定义Dockerfile的绝对路径,因为这些路径会阻止撰写文件可移植。

build:
  context: .
  dockerfile: webapp.Dockerfile

参数

args`定义构建参数,即 Dockerfile 值。`ARG

使用以下 Dockerfile:

ARG GIT_COMMIT
RUN echo "Based on commit: $GIT_COMMIT"
args`可以在“撰写文件”中的键下设置以定义 。 可以设置映射或列表:`build``GIT_COMMIT``args
build:
  context: .
  args:
    GIT_COMMIT: cdc3b19
build:
  context: .
  args:
    - GIT_COMMIT=cdc3b19

指定构建参数时可以省略 Value,在这种情况下,必须在用户交互中获取其在构建时的值,否则在构建 Docker 映像时不会设置 build arg。

args:
  - GIT_COMMIT

断续器

ssh定义了映像生成器在映像构建期间应使用的 SSH 身份验证(例如,克隆专用存储库)

ssh属性语法可以是:

  • default- 让构建器连接到 ssh 代理。
  • ID=path- ID 和关联路径的键/值定义。可以是 PEM 文件,也可以是 ssh 代理套接字的路径

简单示例default

build:
  context: .
  ssh: 
    - default   # mount the default ssh agent

build:
  context: .
  ssh: ["default"]   # mount the default ssh agent

使用具有本地 SSH 密钥路径的自定义 ID:myproject

build:
  context: .
  ssh: 
    - myproject=~/.ssh/myproject.pem

然后,映像生成器可以依靠此在生成期间装载 SSH 密钥。为了便于说明,BuildKit 扩展语法可用于挂载由 ID 设置的 ssh 密钥并访问受保护的资源:

RUN --mount=type=ssh,id=myproject git clone ...

cache_from

cache_from定义了映像生成器用于缓存分辨率的源列表。

缓存位置语法必须遵循全局格式 。简单实际上是 的快捷方式表示法。[NAME|type=TYPE[,KEY=VALUE]]``NAME``type=registry,ref=NAME

撰写生成器实现可能支持自定义类型,撰写规范定义了必须支持的规范类型:

  • registry从按键设置的 OCI 映像中检索构建缓存ref
build:
  context: .
  cache_from:
    - alpine:latest
    - type=local,src=path/to/cache
    - type=gha

必须忽略不受支持的缓存,并且不能阻止用户生成映像。

cache_to

cache_to定义要用于与将来的生成共享生成缓存的导出位置列表。

build:
  context: .
  cache_to: 
   - user/app:cache
   - type=local,dest=path/to/cache

缓存目标使用cache_from定义的相同语法进行定义。type=TYPE[,KEY=VALUE]

必须忽略不受支持的缓存目标,并且不能阻止用户构建映像。

extra_hosts

extra_hosts在构建时添加主机名映射。使用与extra_hosts相同的语法。

extra_hosts:
  - "somehost:162.242.195.82"
  - "otherhost:50.31.209.229"

编写实现必须在容器的网络配置中创建具有IP地址和主机名的匹配条目,这意味着对于Linux将获得额外的行:/etc/hosts

162.242.195.82  somehost
50.31.209.229   otherhost

隔离

isolation指定生成的容器隔离技术。像隔离支持的值是特定于平台的。

标签

labels`将元数据添加到生成的图像。 可以设置为数组或映射。`labels

应使用反向 DNS 表示法来防止标签与其他软件使用的标签冲突。

build:
  context: .
  labels:
    com.example.description: "Accounting webapp"
    com.example.department: "Finance"
    com.example.label-with-empty-value: ""
build:
  context: .
  labels:
    - "com.example.description=Accounting webapp"
    - "com.example.department=Finance"
    - "com.example.label-with-empty-value"

shm_size

shm_size` set the size of the shared memory ( partition on Linux) allocated for building Docker image. Specify as an integer value representing the number of bytes or as a string expressing a [byte value](https://docs.docker.com/compose/compose-file/#specifying-byte-values).`/dev/shm
build:
  context: .
  shm_size: '2gb'
build:
  context: .
  shm_size: 10000000

target

target` defines the stage to build as defined inside a multi-stage .`Dockerfile
build:
  context: .
  target: prod

实现

开源项目

https://docs.halo.run/getting-started/install/other/docker-compose

version: "3"

services:
  halo_server:
    image: halohub/halo:1.5.3
    container_name: halo_server
    restart: on-failure:3
    depends_on:
      - halo_mysql
    networks:
      halo_network:
    volumes:
      - ./:/root/
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "8090:8090"
    environment:
      - SERVER_PORT=8090
      - SPRING_DATASOURCE_DRIVER_CLASS_NAME=com.mysql.cj.jdbc.Driver
      - SPRING_DATASOURCE_URL=jdbc:mysql://halo_mysql:3306/halodb?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
      - SPRING_DATASOURCE_USERNAME=root
      - SPRING_DATASOURCE_PASSWORD=o#DwN&JSa56
      - HALO_ADMIN_PATH=admin
      - HALO_CACHE=memory

  halo_mysql:
    image: mysql:8.0.27
    container_name: halo_mysql
    restart: on-failure:3
    networks:
      halo_network:
    command: --default_authentication_plugin=mysql_native_password
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_general_ci
      --explicit_defaults_for_timestamp=true
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./mysql:/var/lib/mysql
      - ./mysql/mysqlBackup:/data/mysqlBackup
    ports:
      - "3306:3306"
    environment:
      # 请修改此密码,并对应修改上方 Halo 服务的 SPRING_DATASOURCE_PASSWORD 变量值
      - MYSQL_ROOT_PASSWORD=o#DwN&JSa56
      - MYSQL_DATABASE=halodb

networks:
  halo_network:

Docker swarm

蜂群模式概述|Docker 文档

Docker 引擎中嵌入的集群管理和编排功能是使用 swarmkit 构建的。Swarmkit是一个单独的项目,它实现了Docker的编排层,并直接在Docker中使用。

一个群由多个 Docker 主机组成,这些主机以群模式运行,并充当管理器(管理成员资格和委派)和工作线程(运行群服务)。给定的 Docker 主机可以是经理、辅助角色或同时执行这两个角色。创建服务时,需要定义其最佳状态(副本数、可供其使用的网络和存储资源数、服务向外界公开的端口等)。Docker 致力于保持所需的状态。例如,如果一个工作线程节点变得不可用,Docker 会将该节点的任务安排在其他节点上。任务是一个正在运行的容器,它是群服务的一部分,由群管理器管理,而不是独立的容器。

与独立容器相比,swarm 服务的主要优势之一是,您可以修改服务的配置,包括它所连接的网络和卷,而无需手动重新启动服务。Docker 将更新配置,停止具有过期配置的服务任务,并创建与所需配置匹配的新任务。

当 Docker 以群模式运行时,您仍然可以在参与群的任何 Docker 主机以及群服务上运行独立容器。独立容器和群服务之间的一个关键区别是,只有群管理器可以管理群,而独立容器可以在任何守护程序上启动。Docker 守护程序可以作为经理和/或工人参与蜂群。

与使用 Docker Compose 定义和运行容器的方式相同,您可以定义和运行 Swarm 服务堆栈。

继续阅读有关 Docker 群服务相关概念的详细信息,包括节点、服务、任务和负载平衡。

服务和任务

服务是要在管理器或工作节点上执行的任务的定义。它是群系统的中心结构,也是用户与互的主要根源。

创建服务时,请指定要使用的容器映像以及要在正在运行的容器内执行的命令。

复制的服务模型中,swarm 管理器根据在所需状态下设置的规模在节点之间分配特定数量的副本任务。

对于全局服务,swarm 在群集中的每个可用节点上运行一个服务任务。

任务携带一个 Docker 容器和要在容器内运行的命令。它是 swarm 的原子调度单元。管理器节点根据服务规模中设置的副本数将任务分配给工作线程节点。一旦将任务分配给节点,它就不能移动到另一个节点。它只能在分配的节点上运行或失败。

负载均衡

群管理器使用入口负载平衡向群公开要在外部可用的服务。swarm 管理器可以自动为服务分配 **PublishedPort,**或者您可以为该服务配置 PublishedPort。您可以指定任何未使用的端口。如果未指定端口,则 swarm 管理器将为服务分配 30000-32767 范围内的端口。

外部组件(如云负载均衡器)可以访问群集中任何节点的 PublishedPort 上的服务,无论该节点当前是否正在运行该服务的任务。swarm 中的所有节点都将入口连接路由到正在运行的任务实例。

Swarm 模式具有一个内部 DNS 组件,该组件可自动为 Swarm 中的每个服务分配一个 DNS 条目。swarm 管理器使用内部负载平衡,根据服务的 DNS 名称在群集内的服务之间分配请求。

节点的工作原理

预计阅读时间: 2 分钟

Docker 引擎 1.12 引入了群模式,使您能够创建一个或多个 Docker 引擎(称为群)的集群。群由一个或多个节点组成:在群模式下运行 Docker 引擎 1.12 或更高版本的物理机或虚拟机。

有两种类型的节点:经理工作人员

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IIpVGQa4-1653915420758)(…/…/图片/typora/swarm-diagram.png)]

如果尚未阅读,请通读 swarm 模式概述关键概念

管理器节点

管理器节点处理群集管理任务:

使用 Raft 实现,管理器维护整个群及其上运行的所有服务的一致内部状态。出于测试目的,可以使用单个管理器运行一个群。如果单管理器群中的管理器发生故障,您的服务将继续运行,但您需要创建一个新的集群来恢复。

为了利用 swarm 模式的容错功能,Docker 建议你根据组织的高可用性要求实现奇数个节点。当您有多个管理器时,您可以从管理器节点的故障中恢复,而不会造成停机。

  • 三个经理群可以容忍一个经理的最大损失。

  • 五个管理器群允许最大同时丢失两个管理器节点。

  • 管理器集群可以容忍大多数管理器的丢失。N``(N-1)/2

  • Docker 建议一个群最多有七个管理器节点。

    重要说明:添加更多经理并不意味着可伸缩性更高或性能更高。一般来说,情况恰恰相反。

工作节点

工作节点也是 Docker 引擎的实例,其唯一目的是执行容器。工作节点不参与 Raft 分布式状态、做出调度决策或为群模式 HTTP API 提供服务。

您可以创建一个管理器节点的群,但是如果没有至少一个管理器节点,则不能有一个工作线程节点。默认情况下,所有经理也是工作人员。在单个管理器节点集群中,您可以运行命令,例如调度程序将所有任务放在本地引擎上。docker service create

要防止调度程序将任务放在多节点群中的管理节点上,请将管理中心节点的可用性设置为 。计划程序以模式正常停止节点上的任务,并在节点上计划任务。计划程序不会将新任务分配给具有可用性的节点。Drain``Drain``Active``Drain

请参阅 docker 节点更新命令行参考,了解如何更改节点可用性。

更改角色

您可以通过运行 将工作线程节点提升为管理器。例如,您可能希望在使管理器节点脱机以进行维护时升级工作线程节点。请参阅节点提升docker node promote

您还可以将管理器节点降级为工作线程节点。请参阅节点降级

服务的工作原理

预计阅读时间: 5 分钟

若要在 Docker 引擎处于群模式时部署应用程序映像,请创建一个服务。通常,服务是某些较大应用程序上下文中微服务的映像。服务的示例可能包括 HTTP 服务器、数据库或您希望在分布式环境中运行的任何其他类型的可执行程序。

创建服务时,请指定要使用的容器映像以及要在正在运行的容器内执行的命令。您还可以定义服务的选项,包括:

  • 群使服务在群外部可用的端口
  • 用于服务连接到群中其他服务的覆盖网络
  • CPU 和内存限制和预留
  • 滚动更新策略
  • 要在群中运行的映像的副本数

服务、任务和容器

将服务部署到 swarm 时,swarm 管理器会接受您的服务定义作为服务的所需状态。然后,它将群中的节点上的服务调度为一个或多个副本任务。这些任务在群中的节点上彼此独立运行。

例如,假设您希望在 HTTP 侦听器的三个实例之间进行负载平衡。下图显示了具有三个副本的 HTTP 侦听器服务。侦听器的三个实例中的每一个都是群中的一个任务。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yoze5mso-1653915420759)(…/…/图片/typora/services-diagram.png)]

容器是一个隔离的进程。在群模式模型中,每个任务只调用一个容器。任务类似于调度程序放置容器的“槽”。容器处于活动状态后,计划程序会识别出任务处于运行状态。如果容器未通过运行状况检查或终止,则任务将终止。

任务和计划

任务是群中调度的原子单元。通过创建或更新服务来声明所需的服务状态时,业务流程协调程序将通过计划任务来实现所需的状态。例如,定义一个服务,该服务指示业务流程协调程序始终保持 HTTP 侦听器的三个实例运行。业务流程协调程序通过创建三个任务进行响应。每个任务都是计划程序通过生成容器来填充的槽。容器是任务的实例化。如果 HTTP 侦听器任务随后未通过其运行状况检查或崩溃,业务流程协调程序将创建一个新的副本任务,该任务将生成一个新容器。

任务是一种单向机制。它通过一系列状态单调地进行:分配,准备,运行等。如果任务失败,业务流程协调程序将删除该任务及其容器,然后创建一个新任务以根据服务指定的所需状态替换它。

Docker 群模式的底层逻辑是通用调度程序和业务流程协调程序。服务和任务抽象本身并不知道它们实现的容器。假设您可以实现其他类型的任务,例如虚拟机任务或非容器化流程任务。计划程序和业务流程协调程序对任务类型是不可知的。但是,当前版本的 Docker 仅支持容器任务。

下图显示了 swarm 模式如何接受服务创建请求并将任务计划给工作线程节点。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aqv4TtMI-1653915420759)(…/…/图片/typora/service-lifecycle.png)]

待处理的服务

服务可以配置为这样一种方式,即当前在群中的节点都不能运行其任务。在这种情况下,服务将保持状态。下面是服务何时可能保持状态的几个示例。pending``pending

: 如果您的唯一目的是阻止部署服务,请将服务扩展到 0,而不是尝试以使其保留在 中的方式进行配置。pending

  • 如果所有节点都已暂停或耗尽,并且您创建了一个服务,则该服务将处于挂起状态,直到某个节点变为可用。实际上,第一个变为可用的节点将获得所有任务,因此在生产环境中这样做并不是一件好事。
  • 您可以为服务保留特定数量的内存。如果 swarm 中没有节点具有所需的内存量,则服务将保持挂起状态,直到可以运行其任务的节点可用。如果指定一个非常大的值(如 500 GB),则任务将永久保持挂起状态,除非您确实有一个可以满足它的节点。
  • 您可以对服务施加放置约束,但这些约束可能无法在给定时间得到遵守。

此行为说明任务的要求和配置与群的当前状态没有紧密联系。作为群的管理员,您声明了群的所需状态,管理器与群中的节点一起创建该状态。您不需要对群上的任务进行微观管理。

复制和全局服务

有两种类型的服务部署:复制部署和全局部署。

对于复制的服务,可以指定要运行的相同任务的数量。例如,您决定部署具有三个副本的 HTTP 服务,每个副本提供相同的内容。

全局服务是在每个节点上运行一个任务的服务。没有预先指定的任务数。每次将节点添加到群中时,业务流程协调程序都会创建一个任务,并且计划程序会将该任务分配给新节点。全局服务的良好候选者是监视代理、防病毒扫描程序或要在群中的每个节点上运行的其他类型的容器。

下图以黄色显示三个服务副本,以灰色显示全局服务。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TZ0SbYL7-1653915420759)(…/…/图片/typora/replicated-vs-global.png)]

在群模式下运行 Docker 引擎

预计阅读时间: 8 分钟

首次安装并开始使用 Docker 引擎时,默认情况下会禁用 swarm 模式。启用群模式时,可以使用通过命令管理的服务的概念。docker service

有两种方法可以在群模式下运行引擎:

在本地计算机上以群模式运行引擎时,可以根据已创建的映像或其他可用映像创建和测试服务。在生产环境中,swarm 模式提供了一个具有群集管理功能的容错平台,以保持服务运行和可用。

这些说明假定您已在计算机上安装了 Docker 引擎 1.12 或更高版本,以用作群中的管理器节点。

如果尚未通读 swarm 模式关键概念并尝试 swarm 模式教程

创建一个群

当您运行命令以创建群时,Docker 引擎将开始在群模式下运行。

运行 docker swarm init 以在当前节点上创建单节点群。引擎按如下方式设置蜂群:

  • 将当前节点切换到群模式。
  • 创建一个名为 的群。default
  • 将当前节点指定为群的领导者管理器节点。
  • 使用计算机主机名命名节点。
  • 将管理中心配置为侦听端口 2377 上的活动网络接口。
  • 将当前节点设置为可用性,这意味着它可以从计划程序接收任务。Active
  • 为参与群的引擎启动内部分布式数据存储,以保持群和在其上运行的所有服务的一致视图。
  • 默认情况下,为群生成自签名根 CA。
  • 默认情况下, 为工作节点和管理器节点生成令牌以加入 swarm。
  • 创建一个覆盖网络,该网络名为发布群外部的服务端口。ingress
  • 为网络创建覆盖默认 IP 地址和子网掩码

的输出提供了将新工作线程节点加入 swarm 时要使用的连接命令:docker swarm init

$ docker swarm init
Swarm initialized: current node (dxn1zf6l61qsb1josjja83ngz) is now a manager.

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

    docker swarm join \
    --token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c \
    192.168.99.100:2377

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

配置默认地址池

默认情况下,Docker Swarm 对全局作用域(覆盖)网络使用默认地址池。每个未指定子网的网络都将具有从此池中按顺序分配的子网。在某些情况下,可能需要对网络使用不同的默认 IP 地址池。10.0.0.0/8

例如,如果默认范围与网络中已分配的地址空间冲突,则需要确保网络使用不同的范围,而不要求 Swarm 用户使用命令指定每个子网。10.0.0.0/8``--subnet

要配置自定义默认地址池,必须在 Swarm 初始化时使用命令行选项定义池。此命令行选项使用 CIDR 表示法来定义子网掩码。若要为 Swarm 创建自定义地址池,必须至少定义一个默认地址池和可选的默认地址池子网掩码。例如,对于 ,请使用值 。--default-addr-pool``10.0.0.0/27``27

Docker 从该选项指定的地址范围中分配子网地址。例如,命令行选项指示 Docker 将从该地址范围分配子网。如果未指定或显式设置为 24,则将导致 256 个网络的形式。--default-addr-pool``--default-addr-pool 10.10.0.0/16``/16``--default-addr-pool-mask-len``/24``10.10.X.0/24

子网范围来自 、 (例如 )。那里16的大小表示在该范围内可以创建的网络的数量。该选项可能会出现多次,每个选项都为 docker 提供用于覆盖子网的其他地址。--default-addr-pool``10.10.0.0/16``default-addr-pool``--default-addr-pool

该命令的格式为:

$ docker swarm init --default-addr-pool <IP range in CIDR> [--default-addr-pool <IP range in CIDR> --default-addr-pool-mask-length <CIDR value>]

要为 10.20.0.0 网络创建具有 /16(B 类)的默认 IP 地址池,如下所示:

$ docker swarm init --default-addr-pool 10.20.0.0/16

要创建默认 IP 地址池,并为 和 网络创建一个(B 类),并为每个网络创建子网掩码,如下所示:/16``10.20.0.0``10.30.0.0``/26

$ docker swarm init --default-addr-pool 10.20.0.0/16 --default-addr-pool 10.30.0.0/16 --default-addr-pool-mask-length 26

在此示例中,将产生 为 的已分配子网,并将产生 为 的已分配子网。此过程将一直持续到所有子网都用尽为止。docker network create -d overlay net1``10.20.0.0/26``net1``docker network create -d overlay net2``10.20.0.64/26``net2

有关详细信息,请参阅以下页面:

配置播发地址

管理器节点使用通告地址来允许群中的其他节点访问 Swarmkit API 和覆盖网络。群中的其他节点必须能够访问其通告地址上的管理器节点。

如果未指定播发地址,Docker 将检查系统是否具有单个 IP 地址。如果是这样,Docker 默认使用具有侦听端口的 IP 地址。如果系统有多个 IP 地址,则必须指定正确的 IP 地址以启用管理器间通信和覆盖网络:2377``--advertise-addr

$ docker swarm init --advertise-addr <MANAGER-IP>

您还必须指定其他节点到达第一个管理器节点的地址是否与管理器看到的地址不同。例如,在跨不同区域的云设置中,主机既具有用于在区域内进行访问的内部地址,又具有用于从该区域外部进行访问的外部地址。在这种情况下,请指定 外部地址,以便节点可以将该信息传播到随后连接到它的其他节点。--advertise-addr``--advertise-addr

有关播发地址的更多详细信息,请参阅 CLI 参考docker swarm init

查看加入命令或更新群连接令牌

节点需要一个秘密令牌才能加入群。工作线程节点的令牌与管理器节点的令牌不同。节点仅在加入群时使用联接令牌。在节点已加入群后轮换联接令牌不会影响节点的群成员身份。令牌轮换可确保任何尝试加入群的新节点都不能使用旧令牌。

若要检索包含工作线程节点的连接令牌的 join 命令,请运行:

$ docker swarm join-token worker

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

    docker swarm join \
    --token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c \
    192.168.99.100:2377

This node joined a swarm as a worker.

要查看管理节点的 join 命令和令牌,请运行:

$ docker swarm join-token manager

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

    docker swarm join \
    --token SWMTKN-1-59egwe8qangbzbqb3ryawxzk3jn97ifahlsrw01yar60pmkr90-bdjfnkcflhooyafetgjod97sz \
    192.168.99.100:2377

传递标志以仅打印令牌:--quiet

$ docker swarm join-token --quiet worker

SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c

请小心使用联接令牌,因为它们是加入群所必需的机密。特别是,将密钥签入到版本控制中是一种不好的做法,因为它将允许有权访问应用程序源代码的任何人向群中添加新节点。管理器令牌特别敏感,因为它们允许新的管理器节点加入并获得对整个群的控制。

我们建议您在以下情况下轮换联接令牌:

  • 如果令牌意外签入版本控制系统,则进行群聊或意外打印到日志中。
  • 如果您怀疑某个节点已遭到入侵。
  • 如果您希望保证没有新节点可以加入集群。

此外,最佳做法是为任何机密(包括群联接令牌)实现定期轮换计划。我们建议您至少每6个月轮换一次代币。

运行以使旧令牌失效并生成新令牌。指定是否要轮换 节点 的令牌:swarm join-token --rotate``worker``manager

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VA7L66cr-1653915420760)(…/…/图片/typora/1653809323378.png)]

将节点连接到群

预计阅读时间: 3 分钟

首次创建群时,将单个 Docker 引擎置于群模式。要充分利用群模式,您可以将节点添加到群中:

  • 添加工作线程节点可增加容量。将服务部署到群时,引擎会在可用节点上调度任务,无论它们是工作节点还是管理器节点。当您将工人添加到您的集群中时,您可以增加集群的规模来处理任务,而不会影响经理筏的共识。
  • 管理中心节点提高了容错能力。管理器节点执行群的编排和集群管理功能。在管理器节点中,单个领导节点执行编排任务。如果领导节点出现故障,其余的管理节点将选择新的领导节点,并恢复群状态的编排和维护。缺省情况下,管理器节点也运行任务。

Docker 引擎根据您提供给命令的联接令牌加入群。节点仅在加入时使用令牌。如果随后轮换令牌,则不会影响现有的 swarm 节点。请参阅在群模式下运行 Docker 引擎docker swarm join

作为工作线程节点加入

要检索包含工作线程节点的 join 令牌的 join 命令,请在管理器节点上运行以下命令:

$ docker swarm join-token worker

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

    docker swarm join \
    --token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c \
    192.168.99.100:2377

从工作线程上的输出运行命令以加入群:

$ docker swarm join \
  --token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c \
  192.168.99.100:2377

This node joined a swarm as a worker.

该命令执行以下操作:docker swarm join

  • 将当前节点上的 Docker 引擎切换到群模式。
  • 从管理器请求 TLS 证书。
  • 使用计算机主机名命名节点
  • 根据群标记将当前节点加入管理器侦听地址处的群。
  • 将当前节点设置为可用性,这意味着它可以从计划程序接收任务。Active
  • 将覆盖网络扩展到当前节点。ingress

作为管理器节点加入

当您运行并传递管理器令牌时,Docker 引擎将切换到与工作线程相同的群模式。管理器节点也参与筏共识。新节点应该是 ,但现有的管理器仍然是群。docker swarm join``Reachable``Leader

Docker 建议每个集群有三个或五个管理器节点来实现高可用性。由于群模式管理器节点使用 Raft 共享数据,因此必须有奇数个管理器。只要超过一半的管理器节点的仲裁可用,swarm 就可以继续运行。

有关群管理器和管理群的更多详细信息,请参阅管理和维护 Docker 引擎群

要检索包含管理节点的联接令牌的 join 命令,请在管理中心节点上运行以下命令:

$ docker swarm join-token manager

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

    docker swarm join \
    --token SWMTKN-1-61ztec5kyafptydic6jfc1i33t37flcl4nuipzcusor96k7kby-5vy9t8u35tuqm7vh67lrz9xp6 \
    192.168.99.100:2377

从新管理器节点上的输出运行命令,将其加入到群中:

$ docker swarm join \
  --token SWMTKN-1-61ztec5kyafptydic6jfc1i33t37flcl4nuipzcusor96k7kby-5vy9t8u35tuqm7vh67lrz9xp6 \
  192.168.99.100:2377

管理群中的节点

预计阅读时间: 7 分钟

作为群管理生命周期的一部分,您可能需要查看或更新节点,如下所示:

列出节点

要查看从管理器节点运行的群中的节点列表:docker node ls

$ docker node ls

ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
46aqrk4e473hjbt745z53cr3t    node-5    Ready   Active        Reachable
61pi3d91s0w3b90ijw3deeb2q    node-4    Ready   Active        Reachable
a5b2m3oghd48m8eu391pefq5u    node-3    Ready   Active
e7p8btxeu3ioshyuj6lxiv6g0    node-2    Ready   Active
ehkv3bcimagdese79dn78otj5 *  node-1    Ready   Active        Leader

该列显示计划程序是否可以将任务分配给节点:AVAILABILITY

  • Active意味着计划程序可以将任务分配给节点。
  • Pause表示计划程序不会将新任务分配给节点,但现有任务仍保持运行状态。
  • Drain表示计划程序不会将新任务分配给节点。计划程序关闭所有现有任务,并在可用节点上计划它们。

该列显示节点参与 Raft 共识:MANAGER STATUS

  • “无值”指示不参与群管理的工作节点。
  • Leader表示节点是主管理器节点,它为群做出所有群管理和编排决策。
  • Reachable表示该节点是参与 Raft 共识仲裁的管理器节点。如果领导节点变得不可用,则该节点有资格被选为新的领导。
  • Unavailable表示节点是无法与其他管理器通信的管理器。如果管理器节点变得不可用,则应将新的管理器节点加入到群中,或者将工作节点提升为管理器。

有关群管理的更多信息,请参阅群管理指南

检查单个节点

您可以在管理器节点上运行以查看单个节点的详细信息。输出默认为 JSON 格式,但您可以传递标志以人类可读的格式打印结果。例如:docker node inspect <NODE-ID>``--pretty

$ docker node inspect self --pretty

ID:                     ehkv3bcimagdese79dn78otj5
Hostname:               node-1
Joined at:              2016-06-16 22:52:44.9910662 +0000 utc
Status:
 State:                 Ready
 Availability:          Active
Manager Status:
 Address:               172.17.0.2:2377
 Raft Status:           Reachable
 Leader:                Yes
Platform:
 Operating System:      linux
 Architecture:          x86_64
Resources:
 CPUs:                  2
 Memory:                1.954 GiB
Plugins:
  Network:              overlay, host, bridge, overlay, null
  Volume:               local
Engine Version:         1.12.0-dev

更新节点

您可以按如下方式修改节点属性:

更改节点可用性

通过更改节点可用性,您可以:

  • 排出管理器节点,以便仅执行群管理任务,并且不可用于任务分配。
  • 排空节点,以便将其取下以进行维护。
  • 暂停节点,使其无法接收新任务。
  • 恢复不可用或暂停的节点可用状态。

例如,要将管理器节点更改为可用性:Drain

$ docker node update --availability drain node-1

node-1

See list nodes for descriptions of the different availability options.

Add or remove label metadata

Node labels provide a flexible method of node organization. You can also use node labels in service constraints. Apply constraints when you create a service to limit the nodes where the scheduler assigns tasks for the service.

Run on a manager node to add label metadata to a node. The flag supports either a or a pair.docker node update --label-add``--label-add``<key>``<key>=<value>

Pass the flag once for each node label you want to add:--label-add

$ docker node update --label-add foo --label-add bar=baz node-1

node-1

The labels you set for nodes using docker node update apply only to the node entity within the swarm. Do not confuse them with the docker daemon labels for dockerd.

Therefore, node labels can be used to limit critical tasks to nodes that meet certain requirements. For example, schedule only on machines where special workloads should be run, such as machines that meet PCI-SS compliance.

A compromised worker could not compromise these special workloads because it cannot change node labels.

Engine labels, however, are still useful because some features that do not affect secure orchestration of containers might be better off set in a decentralized manner. For instance, an engine could have a label to indicate that it has a certain type of disk device, which may not be relevant to security directly. These labels are more easily “trusted” by the swarm orchestrator.

Refer to the CLI reference for more information about service constraints.docker service create

Promote or demote a node

You can promote a worker node to the manager role. This is useful when a manager node becomes unavailable or if you want to take a manager offline for maintenance. Similarly, you can demote a manager node to the worker role.

Note: Regardless of your reason to promote or demote a node, you must always maintain a quorum of manager nodes in the swarm. For more information refer to the Swarm administration guide.

To promote a node or set of nodes, run from a manager node:docker node promote

$ docker node promote node-3 node-2

Node node-3 promoted to a manager in the swarm.
Node node-2 promoted to a manager in the swarm.

To demote a node or set of nodes, run from a manager node:docker node demote

$ docker node demote node-3 node-2

Manager node-3 demoted in the swarm.
Manager node-2 demoted in the swarm.
docker node promote`并且分别是 和 的便利命令。`docker node demote``docker node update --role manager``docker node update --role worker

在群节点上安装插件

如果您的 swarm 服务依赖于一个或多个插件,则这些插件需要在可能部署服务的每个节点上可用。您可以在每个节点上手动安装插件或编写安装脚本。您还可以使用 Docker API 以类似于全局服务的方式部署插件,方法是指定 一个 而不是 .PluginSpec``ContainerSpec

注意

目前没有办法使用 Docker CLI 或 Docker Compose 将插件部署到群中。此外,无法从私有存储库安装插件。

PluginSpec 由插件开发人员定义。要将插件添加到所有 Docker 节点,请使用 service/create API,传递 在 .PluginSpec``TaskTemplate

离开蜂群

在节点上运行该命令以将其从群中删除。docker swarm leave

例如,将群留在工作节点上:

$ docker swarm leave

Node left the swarm.

当节点离开群时,Docker 引擎将停止以群模式运行。业务流程协调程序不再将任务计划到节点。

如果节点是管理器节点,您将收到有关维护仲裁的警告。要覆盖警告,请传递该标志。如果最后一个管理器节点离开该群,则该群将变得不可用,要求您采取灾难恢复措施。--force

有关维护仲裁和灾难恢复的信息,请参阅 Swarm 管理指南

节点离开群后,可以在管理器节点上运行命令以从节点列表中删除该节点。docker node rm

例如:

$ docker node rm node-2

将服务部署到群

预计阅读时间: 41 分钟

Swarm 服务使用声明性模型,这意味着您可以定义服务的所需状态,并依靠 Docker 来维护此状态。状态包括以下信息(但不限于):

  • 服务容器应运行的映像名称和标记
  • 有多少个容器参与服务
  • 是否有任何端口向群外部的客户端公开
  • 服务是否应该在 Docker 启动时自动启动
  • 重新启动服务时发生的特定行为(例如是否使用滚动重新启动)
  • 可以运行服务的节点的特征(例如资源约束和放置首选项)

有关群模式的概述,请参阅群模式关键概念。有关服务工作原理的概述,请参阅服务的工作原理

创建服务

要创建无额外配置的单副本服务,只需提供映像名称。此命令使用随机生成的名称启动 Nginx 服务,并且没有已发布的端口。这是一个幼稚的例子,因为您无法与Nginx服务进行交互。

$ docker service create nginx

该服务在可用节点上调度。要确认服务已创建并已成功启动,请使用以下命令:docker service ls

$ docker service ls

ID                  NAME                MODE                REPLICAS            IMAGE                                                                                             PORTS
a3iixnklxuem        quizzical_lamarr    replicated          1/1                 docker.io/library/nginx@sha256:41ad9967ea448d7c2b203c699b429abe1ed5af331cd92533900c6d77490e0268

创建的服务并不总是立即运行。如果服务的映像不可用、没有节点满足您为服务配置的要求或其他原因,则该服务可能处于挂起状态。有关详细信息,请参阅挂起的服务

要为服务提供名称,请使用标志:--name

$ docker service create --name my_web nginx

就像独立容器一样,可以通过在映像名称后添加服务容器来指定应运行的命令。此示例启动一个名为的服务,该服务使用映像并运行以下命令:helloworld``alpine``ping docker.com

$ docker service create --name helloworld alpine ping docker.com

您还可以指定服务要使用的图像标记。此示例将前一个示例修改为使用标记:alpine:3.6

$ docker service create --name helloworld alpine:3.6 ping docker.com

有关图像标记分辨率的更多详细信息,请参阅指定服务应使用的图像版本

gMSA for Swarm

Swarm 现在允许使用 Docker Config 作为 gMSA 凭据规范 - 这是 Active Directory 身份验证的应用程序的要求。这减轻了将凭据规范分发到使用它们的节点的负担。

以下示例假定 gMSA 及其凭据规范(称为 credspec.json)已存在,并且正在部署到的节点已针对 gMSA 进行了正确配置。

要将配置用作凭据规范,请首先创建包含凭据规范的 Docker 配置:

$ docker config create credspec credspec.json

现在,您应该有一个名为 credspec 的 Docker 配置,并且可以使用此凭据规范创建服务。为此,请使用带有配置名称的 --credential-spec 标志,如下所示:

$ docker service create --credential-spec="config://credspec" <your image>

服务在启动时使用 gMSA 凭据规范,但与典型的 Docker 配置(通过传递 --config 标志使用)不同,凭据规范不会挂载到容器中。

使用专用注册表上的映像创建服务

如果您的映像在需要登录的专用注册表上可用,请在登录后将标志与 结合使用。如果映像存储在 的 私有注册表中,请使用类似如下的命令:--with-registry-auth``docker service create``registry.example.com

$ docker login registry.example.com

$ docker service  create \
  --with-registry-auth \
  --name my_service \
  registry.example.com/acme/my_image:latest

这将使用加密的 WAL 日志将登录令牌从本地客户端传递到部署服务的 swarm 节点。使用此信息,节点能够登录到注册表并拉取映像。

提供托管服务帐户的凭据规范

在企业版 3.0 中,通过使用 Docker 配置功能集中分发和管理组托管服务帐户 (gMSA) 凭据,提高了安全性。Swarm 现在允许使用 Docker Config 作为 gMSA 凭据规范,这减轻了将凭据规范分发到使用它们的节点的负担。

注意:此选项仅适用于使用 Windows 容器的服务。

凭据规范文件在运行时应用,无需基于主机的凭据规范文件或注册表项 - 不会将 gMSA 凭据写入辅助角色节点上的磁盘。在容器启动之前,可以将凭据规范提供给运行 swarm 工具包工作线程节点的 Docker 引擎。使用基于 gMSA 的配置部署服务时,凭据规范将直接传递到该服务中容器的运行时。

必须是下列格式之一:--credential-spec

  • file://<filename>:引用的文件必须存在于 docker 数据目录的子目录中,这在 Windows 上默认为。例如,指定载荷 。CredentialSpecs``C:\ProgramData\Docker\``file://spec.json``C:\ProgramData\Docker\CredentialSpecs\spec.json
  • registry://<value-name>:从守护程序主机上的 Windows 注册表中读取凭据规范。
  • config://<config-name>:配置名称将自动转换为 CLI 中的配置 ID。使用指定中包含的凭据规范。config

以下简单示例从 Active Directory (AD) 实例中检索 gMSA 名称和 JSON 内容:

$ name="mygmsa"
$ contents="{...}"
$ echo $contents > contents.json

确保为 gMSA 正确配置了要部署到的节点。

要将配置用作凭据规范,请在名为 的凭据规范文件中创建 Docker 配置。您可以为 指定任何名称。credpspec.json``config

$ docker config create --label com.docker.gmsa.name=mygmsa credspec credspec.json

现在,您可以使用此凭据规范创建服务。使用配置名称指定标志:--credential-spec

$ docker service create --credential-spec="config://credspec" <your image>

服务在启动时使用 gMSA 凭据规范,但与典型的 Docker 配置(通过传递 --config 标志使用)不同,凭据规范不会挂载到容器中。

更新服务

您可以使用该命令更改有关现有服务的几乎所有内容。更新服务时,Docker 会停止其容器并使用新配置重新启动它们。docker service update

由于Nginx是一个Web服务,因此如果您将端口80发布到集群外部的客户端,则其工作效果要好得多。您可以在创建服务时使用 or 标志指定此项。更新现有服务时,标志为 。还有一个标志用于删除以前发布的端口。-p``--publish``--publish-add``--publish-rm

假定上一节中的服务仍然存在,请使用以下命令将其更新为发布端口 80。my_web

$ docker service update --publish-add 80 my_web

要验证它是否有效,请使用:docker service ls

$ docker service ls

ID                  NAME                MODE                REPLICAS            IMAGE                                                                                             PORTS
4nhxl7oxw5vz        my_web              replicated          1/1                 docker.io/library/nginx@sha256:41ad9967ea448d7c2b203c699b429abe1ed5af331cd92533900c6d77490e0268   *:0->80/tcp

有关发布端口的工作原理的详细信息,请参阅发布端口

您可以更新有关现有服务的几乎所有配置详细信息,包括映像名称和它运行的标记。请参阅创建后更新服务的映像

删除服务

若要删除服务,请使用该命令。您可以按服务的 ID 或名称删除服务,如命令输出中所示。以下命令将删除该服务。docker service remove``docker service ls``my_web

$ docker service remove my_web

服务配置详细信息

以下各节提供有关服务配置的详细信息。本主题不涵盖每个标志或方案。在几乎所有可以在创建服务时定义配置的实例中,也可以以类似的方式更新现有服务的配置。

请参阅 docker 服务创建和 docker 服务更新的命令行参考,或使用该标志运行其中一个命令。--help

配置运行时环境

您可以为容器中的运行时环境配置以下选项:

  • 使用标志的环境变量--env
  • 容器内使用标志的工作目录--workdir
  • 使用标志的用户名或 UID--user

以下服务的容器将环境变量设置为 ,从目录运行,并以用户身份运行。$MYVAR``myvalue``/tmp/``my_user

$ docker service create --name helloworld \
  --env MYVAR=myvalue \
  --workdir /tmp \
  --user my_user \
  alpine ping docker.com

更新现有服务运行的命令

若要更新现有服务运行的命令,可以使用该标志。下面的示例更新调用的现有服务,以便它运行该命令,而不是之前运行的任何命令:--args``helloworld``ping docker.com

$ docker service update --args "ping docker.com" helloworld

指定服务应使用的映像版本

在创建服务时,如果未指定有关要使用的映像版本的任何详细信息,则该服务将使用标记有标记的版本。可以通过几种不同的方式强制服务使用特定版本的映像,具体取决于所需的结果。latest

映像版本可以用几种不同的方式表示:

  • 如果指定标记,则管理器(或 Docker 客户端,如果使用内容信任)会将该标记解析为摘要。当在工作节点上收到创建容器任务的请求时,工作节点只能看到摘要,而看不到标记。

    $ docker service create --name="myservice" ubuntu:16.04
    

    某些标记表示离散版本,例如 .像这样的标签几乎总是随着时间的推移解析为稳定的摘要。建议您尽可能使用此类标记。ubuntu:16.04

    其他类型的标记(如 or )可能会经常解析为新的摘要,具体取决于图像作者更新标记的频率。不建议使用频繁更新的标签运行服务,以防止不同的服务副本任务使用不同的镜像版本。latest``nightly

  • 如果根本不指定版本,则按照惯例,图像的标记将解析为摘要。工作人员在创建服务任务时使用此摘要中的映像。latest

    因此,以下两个命令是等效的:

    $ docker service create --name="myservice" ubuntu
    
    $ docker service create --name="myservice" ubuntu:latest
    
  • 如果直接指定摘要,则在创建服务任务时始终使用该确切版本的映像。

    $ docker service create \
        --name="myservice" \
        ubuntu:16.04@sha256:35bc48a1ca97c3971611dc4662d08d131869daa692acb281c7e9e052924e38b1
    

创建服务时,映像的标记将解析为创建服务时标记指向的特定摘要。该服务的工作节点将永远使用该特定摘要,除非该服务已显式更新。如果确实使用经常更改的标记(如 ),则此功能尤其重要,因为它可确保所有服务任务都使用相同版本的映像。latest

注意:如果启用了内容信任,客户端实际上会将映像的标记解析为摘要,然后再联系 swarm 管理器,以验证映像是否已签名。因此,如果使用内容信任,则群管理器将收到预先解析的请求。在这种情况下,如果客户端无法将映像解析为摘要,则请求将失败。

如果管理器无法将标记解析为摘要,则每个工作节点负责将标记解析为摘要,并且不同的节点可能使用不同版本的映像。如果发生这种情况,则会记录如下所示的警告,用占位符替换真实信息。

unable to pin image <IMAGE-NAME> to digest: <REASON>

若要查看图像的当前摘要,请发出命令并查找该行。以下是编写此内容时的当前摘要。为清楚起见,输出将被截断。docker inspect <IMAGE>:<TAG>``RepoDigests``ubuntu:latest

$ docker inspect ubuntu:latest
"RepoDigests": [
    "ubuntu@sha256:35bc48a1ca97c3971611dc4662d08d131869daa692acb281c7e9e052924e38b1"
],

创建服务后,其映像永远不会更新,除非您显式运行该标志,如下所述。其他更新操作(如缩放服务、添加或删除网络或卷、重命名服务或任何其他类型的更新操作)不会更新服务的映像。docker service update``--image

创建后更新服务的映像

每个标记表示一个摘要,类似于 Git 哈希。某些标记(如 )经常更新以指向新的摘要。其他的,例如,表示已发布的软件版本,并且不希望经常更新以指向新的摘要(如果有的话)。创建服务时,在使用标志更新服务之前,使用图像的特定摘要创建任务受到限制。latest``ubuntu:16.04``service update``--image

使用该标志运行时,swarm 管理器会查询 Docker 中心或专用 Docker 注册表,以获取标记当前指向的摘要,并更新服务任务以使用该摘要。service update``--image

注意:如果您使用内容信任,Docker 客户端将解析映像,swarm 管理器将接收映像和摘要,而不是标记。

通常,管理器可以将标记解析为新的摘要和服务更新,从而重新部署每个任务以使用新映像。如果经理无法解决代码或出现其他问题,则接下来的两节将概述预期结果。

如果管理器解析标记

如果 swarm 管理器可以将映像标记解析为摘要,它将指示工作线程节点重新部署任务并在该摘要中使用映像。

  • 如果工作线程在该摘要中缓存了图像,它将使用它。
  • 如果没有,它会尝试从 Docker 中心或专用注册表中提取映像。
    • 如果成功,则使用新映像部署任务。
    • 如果辅助角色无法拉取映像,则服务将无法在该工作节点上部署。Docker 再次尝试部署任务,可能部署在不同的工作节点上。
如果管理器无法解析标记

如果 swarm 管理器无法将映像解析为摘要,则不会丢失所有内容:

  • 管理器指示工作线程节点使用该标记处的映像重新部署任务。
  • 如果工作线程具有解析为该标记的本地缓存映像,则它将使用该映像。
  • 如果辅助角色没有解析为标记的本地缓存映像,则辅助角色会尝试连接到 Docker 中心或专用注册表,以在该标记处拉取映像。
    • 如果此操作成功,则工作人员将使用该映像。
    • 如果此操作失败,则任务将无法部署,并且管理器会再次尝试部署该任务,可能在其他工作节点上。

发布端口

创建 swarm 服务时,可以通过两种方式将该服务的端口发布到 swarm 外部的主机:

  • 您可以依赖路由网格。发布服务端口时,swarm 使服务在每个节点上的目标端口上都可访问,而不管该节点上是否正在运行该服务的任务。这并不复杂,是许多类型服务的正确选择。
  • 您可以直接在运行服务的 swarm 节点上发布该服务的端口。这绕过了路由网格,并提供了最大的灵活性,包括您开发自己的路由框架的能力。但是,您负责跟踪每个任务的运行位置并将请求路由到任务,并在节点之间进行负载平衡。

继续阅读以获取这些方法的更多信息和用例。

使用路由网格发布服务的端口

要将服务的端口发布到 swarm 外部,请使用该标志。swarm 使服务可以在每个 swarm 节点上的已发布端口上访问。如果外部主机连接到任何 swarm 节点上的该端口,则路由网格会将其路由到任务。外部主机不需要知道服务任务的 IP 地址或内部使用的端口即可与服务交互。当用户或进程连接到服务时,任何运行服务任务的工作节点都可能响应。有关群业务组网的详细信息,请参见管理群服务网络--publish <PUBLISHED-PORT>:<SERVICE-PORT>

示例:在 10 节点群上运行三任务 Nginx 服务

假设您有一个 10 节点群,并且您部署了一个 Nginx 服务,该服务在 10 节点群上运行三个任务:

$ docker service create --name my_web \
                        --replicas 3 \
                        --publish published=8080,target=80 \
                        nginx

三个任务在最多三个节点上运行。您不需要知道哪些节点正在运行任务;连接到 10 个节点中任何一个节点上的端口 8080 都会将您连接到三个任务之一。您可以使用 对此进行测试。下面的示例假定这是群节点之一。如果不是这种情况,或者不能解析为主机上的 IP 地址,请替换主机的 IP 地址或可解析的主机名。nginx``curl``localhost``localhost

HTML 输出被截断:

$ curl localhost:8080

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...truncated...
</html>

后续连接可以路由到同一 swarm 节点或不同的群节点。

直接在 swarm 节点上发布服务的端口

如果需要根据应用程序状态做出路由决策,或者需要完全控制将请求路由到服务任务的过程,则使用路由网格可能不是应用程序的正确选择。要直接在运行服务的节点上发布服务的端口,请使用标志选项。mode=host``--publish

注意:如果直接在 swarm 节点上发布服务的端口,并且还设置了此功能,则会创建一个隐式限制,即您只能在给定的 swarm 节点上运行该服务的一个任务。您可以通过在不指定端口定义的情况下解决此问题,这会导致 Docker 为每个任务分配一个随机端口。mode=host``published=<PORT>``published

此外,如果您使用 并且不使用 的标志,则很难知道哪些节点正在运行服务以将工作路由到它们。mode=host``--mode=global``docker service create

示例:在每个 swarm 节点上运行 Web 服务器服务nginx

nginx是一个开源的反向代理,负载均衡器,HTTP缓存和Web服务器。如果您使用路由网格将nginx作为服务运行,则连接到任何swarm节点上的nginx端口都会显示(有效地)运行该服务的随机swarm节点的网页。

以下示例在 swarm 中的每个节点上运行 nginx 作为服务,并在每个 swarm 节点上本地公开 nginx 端口。

$ docker service create \
  --mode global \
  --publish mode=host,target=80,published=8080 \
  --name=nginx \
  nginx:latest

您可以在每个 swarm 节点的端口 8080 上访问 nginx 服务器。如果将节点添加到群中,则会在其上启动 nginx 任务。不能在绑定到端口 8080 的任何 swarm 节点上启动另一个服务或容器。

注意:这是一个幼稚的例子。为多层服务创建应用层路由框架很复杂,超出了本主题的范围。

将服务连接到覆盖网络

您可以使用覆盖网络来连接群中的一个或多个服务。

首先,使用带有标志的命令在管理器节点上创建覆盖网络。docker network create``--driver overlay

$ docker network create --driver overlay my-network

在群模式下创建覆盖网络后,所有管理中心节点都可以访问该网络。

您可以创建一个新服务并传递标志以将该服务附加到覆盖网络:--network

$ docker service create \
  --replicas 3 \
  --network my-network \
  --name my-web \
  nginx

swarm 将扩展到运行服务的每个节点。my-network

您还可以使用标志将现有服务连接到覆盖网络。--network-add

$ docker service update --network-add my-network my-web

要断开正在运行的服务与网络的连接,请使用该标志。--network-rm

$ docker service update --network-rm my-network my-web

有关覆盖网络和服务发现的详细信息,请参阅将服务附加到覆盖网络Docker 群模式覆盖网络安全模型

授予服务对机密的访问权限

若要创建有权访问 Docker 托管机密的服务,请使用该标志。有关详细信息,请参阅管理 Docker 服务的敏感字符串(机密)--secret

自定义服务的隔离模式

Docker 允许您指定群服务的隔离模式。**此设置仅适用于 Windows 主机,对于 Linux 主机将被忽略。**隔离模式可以是下列模式之一:

  • default:使用为 Docker 主机配置的默认隔离模式,该模式由 中的标志或数组配置。如果守护程序未指定隔离技术,则 它是 Windows Server 的默认值,并且是 Windows 10 的默认(且唯一)选项。-exec-opt``exec-opts``daemon.json``process``hyperv

  • process:将服务任务作为单独的进程在主机上运行。

    注意:隔离模式仅在 Windows Server 上受支持。Windows 10 仅支持隔离模式。process``hyperv

  • hyperv:将服务任务作为独立任务运行。这会增加开销,但会提供更多的隔离。hyperv

您可以在使用标志创建或更新新服务时指定隔离模式。--isolation

控制服务放置

Swarm 服务提供了几种不同的方法来控制服务在不同节点上的规模和位置。

  • 您可以指定服务是需要运行特定数量的副本,还是应该在每个工作节点上全局运行。请参阅复制或全局服务

  • 您可以配置服务的 CPU 或内存要求,并且服务仅在可以满足这些要求的节点上运行。

  • 放置约束允许您将服务配置为仅在具有特定(任意)元数据集的节点上运行,并在适当的节点不存在时导致部署失败。例如,您可以指定服务应仅在任意标签设置为 的节点上运行。pci_compliant``true

  • 通过放置首选项,您可以将具有一系列值的任意标签应用于每个节点,并使用算法将服务的任务分散到这些节点上。目前,唯一支持的算法是 ,它试图均匀地放置它们。例如,如果您使用值为 1-10 的标签标记每个节点,然后指定键控上的放置首选项,则在考虑其他放置约束、放置首选项和其他特定于节点的限制后,服务任务将尽可能均匀地放置在具有标签的所有节点上。spread``rack``rack``rack

    与约束不同,放置首选项是尽力而为的,如果没有节点可以满足首选项,则服务不会失败部署。如果为服务指定放置首选项,那么当群管理器决定哪些节点应运行服务任务时,与该首选项匹配的节点的排名会更高。其他因素(如服务的高可用性)也会影响计划哪些节点来运行服务任务。例如,如果您有 N 个带有机架标签的节点(然后是其他一些节点),并且您的服务配置为运行 N+1 个副本,则 +1 将调度在一个节点上,该节点上还没有该服务(如果有),而不管该节点是否具有该标签。rack

复制或全局服务

Swarm 模式有两种类型的服务:复制服务和全局。对于复制的服务,您可以指定 swarm 管理器要调度到可用节点上的副本任务数。对于全局服务,计划程序在每个可用节点上放置一个任务,以满足服务的放置约束和资源要求

您可以使用标志控制服务类型。如果未指定模式,则服务默认为 。对于复制的服务,您可以指定要使用标志开始的副本任务数。例如,要启动具有 3 个副本任务的复制 nginx 服务:--mode``replicated``--replicas

$ docker service create \
  --name my_web \
  --replicas 3 \
  nginx

要在每个可用节点上启动全局服务,请传递给 。每当新节点变为可用时,调度程序都会将全局服务的任务放在新节点上。例如,要启动在群中的每个节点上运行 alpine 的服务:--mode global``docker service create

$ docker service create \
  --name myservice \
  --mode global \
  alpine top

服务约束允许您在计划程序将服务部署到节点之前为节点设置要满足的条件。您可以根据节点属性和元数据或引擎元数据将约束应用于服务。有关约束的详细信息,请参阅 CLI 参考docker service create

为服务保留内存或 CPU

要为服务保留给定的内存量或 CPU 数量,请使用 or 标志。如果没有可用节点可以满足要求(例如,如果您请求 4 个 CPU,而群中没有一个节点有 4 个 CPU),则服务将保持挂起状态,直到有适当的节点可用于运行其任务。--reserve-memory``--reserve-cpu

内存不足异常 (OOME)

如果您的服务尝试使用的内存超过 swarm 节点的可用内存,则可能会遇到内存不足异常 (OOME),并且容器或 Docker 守护程序可能被内核 OOM 杀手杀死。若要防止发生这种情况,请确保应用程序在具有足够内存的主机上运行,并参阅了解内存不足的风险

Swarm 服务允许您使用资源约束、放置首选项和标签来确保将服务部署到相应的 swarm 节点。

放置约束

使用放置约束来控制服务可以分配到的节点。在以下示例中,服务仅在标签设置为 的节点上运行。如果没有适当标记的节点可用,则任务将等待,直到它们变为可用。该标志使用相等运算符 ( 或 )。对于复制的服务,可能是所有服务都在同一节点上运行,或者每个节点只运行一个副本,或者某些节点不运行任何副本。对于全局服务,服务在满足放置约束和任何资源要求的每个节点上运行。region``east``Pending``--constraint``==``!=

$ docker service create \
  --name my-nginx \
  --replicas 5 \
  --constraint node.labels.region==east \
  nginx

还可以在文件中使用服务级别键。constraint``docker-compose.yml

如果指定多个放置约束,则服务仅部署到满足所有约束条件的节点上。下面的示例将服务限制为在设置为 和 未设置为 的所有节点上运行:region``east``type``devel

$ docker service create \
  --name my-nginx \
  --mode global \
  --constraint node.labels.region==east \
  --constraint node.labels.type!=devel \
  nginx

您还可以将放置约束与放置首选项和 CPU/内存约束结合使用。请注意不要使用无法实现的设置。

有关约束的详细信息,请参阅 CLI 参考docker service create

放置首选项

虽然放置约束限制了服务可以运行的节点,但放置首选项尝试以算法方式将任务放在适当的节点上(目前,仅均匀分布)。例如,如果为每个节点分配一个标签,则可以设置放置首选项,以便按值将服务均匀地分布在具有标签的节点上。这样,如果丢失了机架,该服务仍在其他机架上的节点上运行。rack``rack

不会严格执行放置首选项。如果没有节点具有您在首选项中指定的标签,则部署服务时就像未设置首选项一样。

全局服务的放置首选项将被忽略。

下面的示例设置一个首选项,以根据标签的值跨节点分布部署。如果某些节点有,而其他节点有 ,则服务将尽可能均匀地部署在两组节点上。datacenter``datacenter=us-east``datacenter=us-west

$ docker service create \
  --replicas 9 \
  --name redis_2 \
  --placement-pref 'spread=node.labels.datacenter' \
  redis:3.0.6

标签缺失或为空

缺少用于传播的标签的节点仍会收到任务分配。作为一个组,这些节点接收的任务与由特定标签值标识的任何其他组的比例相等。从某种意义上说,缺少的标签与附加了 null 值的标签相同。如果服务应仅在标签用于传播首选项的节点上运行,则该首选项应与约束相结合。

您可以指定多个放置首选项,这些首选项将按照遇到它们的顺序进行处理。以下示例设置具有多个放置首选项的服务。任务首先分布在各个数据中心,然后分布在机架上(如相应的标签所示):

$ docker service create \
  --replicas 9 \
  --name redis_2 \
  --placement-pref 'spread=node.labels.datacenter' \
  --placement-pref 'spread=node.labels.rack' \
  redis:3.0.6

您还可以将放置首选项与放置约束或 CPU/内存约束结合使用。请注意不要使用无法实现的设置。

下图说明了放置首选项的工作原理:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SlXVohJ9-1653915420760)(…/…/图片/typora/placement_prefs.png)]

使用 更新服务时,会在所有现有放置首选项之后附加新的放置首选项。 删除与参数匹配的现有放置首选项。docker service update``--placement-pref-add``--placement-pref-rm

配置服务的更新行为

创建服务时,可以指定滚动更新行为,以了解在运行 时,swarm 应如何将更改应用于服务。还可以将这些标志指定为更新的一部分,作为 的参数。docker service update``docker service update

该标志配置更新服务任务或任务集之间的时间延迟。您可以将时间描述为秒数、分钟数或小时数的组合。因此表示延迟 10 分 30 秒。--update-delay``T``Ts``Tm``Th``10m30s

默认情况下,计划程序一次更新 1 个任务。您可以传递该标志来配置计划程序同时更新的最大服务任务数。--update-parallelism

当对单个任务的更新返回状态时,计划程序会继续更新,直到所有任务都更新完毕。如果在更新过程中的任何时候返回任务,计划程序将暂停更新。可以使用 的标志来控制行为, 或 。RUNNING``FAILED``--update-failure-action``docker service create``docker service update

在下面的示例服务中,计划程序一次最多将更新应用于 2 个副本。当更新的任务返回 或 时,计划程序将等待 10 秒钟,然后再停止下一个要更新的任务:RUNNING``FAILED

$ docker service create \
  --replicas 10 \
  --name my_web \
  --update-delay 10s \
  --update-parallelism 2 \
  --update-failure-action continue \
  alpine

该标志控制在将整个更新视为失败之前,在更新期间可以失败的任务的哪一部分。例如,在 10% 的更新任务失败后,如果出现 ,则更新将暂停。--update-max-failure-ratio``--update-max-failure-ratio 0.1 --update-failure-action pause

如果单个任务未启动,或者如果在使用标志指定的监视期限内停止运行,则认为该任务更新已失败。的默认值为 30 秒,这意味着任务在启动后的前 30 秒内失败将计入服务更新失败阈值,之后的失败不计算在内。--update-monitor``--update-monitor

回滚到服务的以前版本

如果服务的更新版本无法按预期运行,则可以使用 的标志手动回滚到服务的以前版本。这会将服务还原到最新命令之前所在的配置。docker service update``--rollback``docker service update

其他选项可以与 ;例如,要在任务之间不延迟地执行回滚:--rollback``--update-delay 0s

$ docker service update \
  --rollback \
  --update-delay 0s
  my_web

可以将服务配置为在部署服务更新失败时自动回滚。请参阅更新失败时自动回滚

手动回滚在服务器端处理,这允许手动启动的回滚遵循新的回滚参数。请注意,不能与其他标志结合使用。--rollback``docker service update

更新失败时自动回滚

您可以通过以下方式配置服务:如果对服务的更新导致重新部署失败,则该服务可以自动回滚到以前的配置。这有助于保护服务可用性。您可以在创建或更新服务时设置以下一个或多个标志。如果未设置值,则使用默认值。

违约描述
--rollback-delay0s回滚任务后在回滚下一个任务之前要等待的时间量。在部署第一个回滚任务后立即回滚第二个任务的 means 值。0
--rollback-failure-actionpause当任务回滚失败时,是回滚还是尝试回滚其他任务。pause``continue
--rollback-max-failure-ratio0回滚期间允许的故障率,指定为介于 0 和 1 之间的浮点数。例如,给定 5 个任务,失败率将容忍一个任务无法回滚。值 1 表示不允许失败,而值 1 表示允许任意数量的故障。.2``0``1
--rollback-monitor5s每个任务回滚后的持续时间,用于监视故障。如果任务在此时间段过后停止,则认为回滚失败。
--rollback-parallelism1要并行回滚的最大任务数。默认情况下,一次回滚一个任务。的值将导致并行回滚所有任务。0

下面的示例将服务配置为在部署失败时自动回滚。可以并行回滚两个任务。回滚后,将监视任务 20 秒,以确保它们不会退出,并且允许的最大故障率为 20%。缺省值用于 和 。redis``docker service update``--rollback-delay``--rollback-failure-action

$ docker service create --name=my_redis \
                        --replicas=5 \
                        --rollback-parallelism=2 \
                        --rollback-monitor=20s \
                        --rollback-max-failure-ratio=.2 \
                        redis:latest

授予服务对卷或绑定装载的访问权限

为了获得最佳性能和可移植性,应避免将重要数据直接写入容器的可写层,而是使用数据卷或绑定装载。这一原则也适用于服务。

您可以为群中的服务创建两种类型的挂载,即挂载或挂载。无论使用哪种类型的挂载,请在创建服务时使用标志或更新现有服务时使用 or 标志对其进行配置。如果未指定类型,则默认值为数据卷。volume``bind``--mount``--mount-add``--mount-rm

数据卷

数据卷是独立于容器存在的存储。swarm 服务下数据卷的生命周期与容器下的生命周期类似。卷的寿命超过任务和服务,因此必须单独管理其删除。可以在部署服务之前创建卷,或者,如果在特定主机上计划任务时,卷在特定主机上不存在,则会根据服务上的卷规范自动创建卷。

要将现有数据卷与服务一起使用,请使用标志:--mount

$ docker service create \
  --mount src=<VOLUME-NAME>,dst=<CONTAINER-PATH> \
  --name myservice \
  <IMAGE>

如果在将任务调度到特定主机时不存在具有相同卷的卷,则会创建一个卷。缺省卷驱动程序是 。若要将其他卷驱动程序与此按需创建模式结合使用,请使用以下标志指定驱动程序及其选项:<VOLUME-NAME>``local``--mount

$ docker service create \
  --mount type=volume,src=<VOLUME-NAME>,dst=<CONTAINER-PATH>,volume-driver=<DRIVER>,volume-opt=<KEY0>=<VALUE0>,volume-opt=<KEY1>=<VALUE1>
  --name myservice \
  <IMAGE>

有关如何创建数据卷和使用卷驱动程序的详细信息,请参阅使用卷

绑定挂载

绑定装载是从调度程序为任务部署容器的主机的文件系统路径。Docker 将路径装载到容器中。在 swarm 初始化任务的容器之前,文件系统路径必须存在。

以下示例显示了绑定装载语法:

  • 挂载读写绑定:

    $ docker service create \
      --mount type=bind,src=<HOST-PATH>,dst=<CONTAINER-PATH> \
      --name myservice \
      <IMAGE>
    
  • 挂载只读绑定:

    $ docker service create \
      --mount type=bind,src=<HOST-PATH>,dst=<CONTAINER-PATH>,readonly \
      --name myservice \
      <IMAGE>
    

重要提示:绑定挂载可能很有用,但也可能导致问题。在大多数情况下,建议您构建应用程序,以便不需要从主机装载路径。主要风险包括:

  • 如果将主机路径绑定到服务的容器中,则该路径必须存在于每个 swarm 节点上。Docker 群模式调度程序可以在满足资源可用性要求并满足您指定的所有约束和放置首选项的任何计算机上调度容器。
  • Docker 群模式调度程序可能会在正在运行的服务容器变得不正常或无法访问时随时重新调度它们。
  • 主机绑定装载是不可移植的。使用绑定装载时,无法保证应用程序在开发中的运行方式与在生产环境中的运行方式相同。

使用模板创建服务

您可以使用 Go 的文本/模板包提供的语法对 的某些标志使用模板。service create

支持以下标志:

  • --hostname
  • --mount
  • --env

Go 模板的有效占位符包括:

占 位 符描述
.Service.ID服务编号
.Service.Name服务名称
.Service.Labels服务标签
.Node.ID节点标识
.Node.Hostname节点主机名
.Task.Name任务名称
.Task.Slot任务槽
模板示例

此示例根据服务的名称和运行容器的节点的 ID 设置所创建容器的模板:

$ docker service create --name hosttempl \
                        --hostname="{{.Node.ID}}-{{.Service.Name}}"\
                         busybox top

若要查看使用模板的结果,请使用 and 命令。docker service ps``docker inspect

$ docker service ps va8ew30grofhjoychbr6iot8c

ID            NAME         IMAGE                                                                                   NODE          DESIRED STATE  CURRENT STATE               ERROR  PORTS
wo41w8hg8qan  hosttempl.1  busybox:latest@sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912  2e7a8a9c4da2  Running        Running about a minute ago
$ docker inspect --format="{{.Config.Hostname}}" hosttempl.1.wo41w8hg8qanxwjwsg4kxpprj

raft

,src=,dst=,volume-driver=,volume-opt==,volume-opt==
–name myservice


有关如何创建数据卷和使用卷驱动程序的详细信息,请参阅[使用卷](https://docs.docker.com/storage/volumes/)。

#### 绑定挂载

绑定装载是从调度程序为任务部署容器的主机的文件系统路径。Docker 将路径装载到容器中。在 swarm 初始化任务的容器之前,文件系统路径必须存在。

以下示例显示了绑定装载语法:

- 挂载读写绑定:

$ docker service create
–mount type=bind,src=,dst=
–name myservice


- 挂载只读绑定:

$ docker service create
–mount type=bind,src=,dst=,readonly
–name myservice


> **重要提示**:绑定挂载可能很有用,但也可能导致问题。在大多数情况下,建议您构建应用程序,以便不需要从主机装载路径。主要风险包括:
>
> - 如果将主机路径绑定到服务的容器中,则该路径必须存在于每个 swarm 节点上。Docker 群模式调度程序可以在满足资源可用性要求并满足您指定的所有约束和放置首选项的任何计算机上调度容器。
> - Docker 群模式调度程序可能会在正在运行的服务容器变得不正常或无法访问时随时重新调度它们。
> - 主机绑定装载是不可移植的。使用绑定装载时,无法保证应用程序在开发中的运行方式与在生产环境中的运行方式相同。

### 使用模板创建服务

您可以使用 Go [的文本/](https://golang.org/pkg/text/template/)模板包提供的语法对 的某些标志使用模板。`service create`

支持以下标志:

- `--hostname`
- `--mount`
- `--env`

Go 模板的有效占位符包括:

| 占 位 符          | 描述       |
| ----------------- | ---------- |
| `.Service.ID`     | 服务编号   |
| `.Service.Name`   | 服务名称   |
| `.Service.Labels` | 服务标签   |
| `.Node.ID`        | 节点标识   |
| `.Node.Hostname`  | 节点主机名 |
| `.Task.Name`      | 任务名称   |
| `.Task.Slot`      | 任务槽     |

#### 模板示例

此示例根据服务的名称和运行容器的节点的 ID 设置所创建容器的模板:

$ docker service create --name hosttempl
–hostname=“{{.Node.ID}}-{{.Service.Name}}”
busybox top


若要查看使用模板的结果,请使用 and 命令。`docker service ps``docker inspect`

$ docker service ps va8ew30grofhjoychbr6iot8c

ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
wo41w8hg8qan hosttempl.1 busybox:latest@sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912 2e7a8a9c4da2 Running Running about a minute ago
$ docker inspect --format=“{{.Config.Hostname}}” hosttempl.1.wo41w8hg8qanxwjwsg4kxpprj


# raft

Raft协议:保证大多数节点存活才可用。只要>1 ,集群至少大于3台,至少存在3个master节点,如果一个master节点挂了,则会从另外两个备节点选举。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

期待未来的男孩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值