详解 docker create service 的 --publish 参数

参数--publish(-p)用来把容器里的端口映射到主机外面来。

基本格式

有两种格式:

  1. 短格式: <externport>:<internport>
  2. 长格式:[mode=host],published=<externport>,target=<internport>

短格式只能标识两个参数即可,外部端口:内部端口,长格式还可以标识mode参数。

mode=ingress|host 的用法

格式:mode=[ingress|host],其中ingress是缺省格式,含义:

  1. ingress把端口映射到整个swarm的网络,从而访问swarm网络的任何一台主机都可以,即使这台主机没有一个service的container在运行。
  2. host只把端口映射到service的container所在运行的主机,其他主机就不能访问。

举个例子:
假设swarm网络有两台主机构成:hostA,hostB:

  1. 在hostA上运行下面命令创建一个service,包含缺省一个container:
    $ docker service create --name mynginx -p published=20000,target=80 nginx
  2. 此时它会创建一个service,包含一个container,这个container被分配到hostA或者hostB随机。

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
qyw58qcs4xrh        mynginx             replicated          1/1                 nginx:latest        *:20000->80/tcp

我们在hostA上ping 2000端口

$ curl localhost:20000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
...

如果我们在hostB上也访问20000端口

$ curl localhost:20000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
...

在两台主机上都能访问20000端口,尽管service只有一个container运行在其中一台主机上。

下面一个测试,我们指定mode=host。

  1. 在hostA上运行:
    $ docker service create --name mynginx -p mode=host,published=20000,target=80 nginx
  2. 在hostA上查看container

$ docker ps | grep nginx
  1. 在hostB上查看container

$ docker ps | grep nginx
df3216d6b665        nginx:latest             "nginx -g 'daemon of…"   About a minute ago   Up About a minute   0.0.0.0:20000->80/tcp                        mynginx.1.if3z9quqscqdbg87cjzmlwkdm

此时container被随机分配到了hostB上。

在hostA访问20000端口

$ curl 127.0.0.1:20000
curl: (56) Recv failure: Connection reset by peer

在hostB访问20000端口

$ curl localhost:20000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
...

可以看见container运行在hostB上,那么hostB的20000端口可以访问,而hostA的20000端口就不能访问了。

此时我们会想到可能有另外一个问题,即:如果在两个node的主机上使用mode=host创建3个以上的container的,那么必然有一个host上有两个container,他们同时都要映射20000端口会不会有问题? 实验一下:

$ docker service create --name mynginx --replicas=3 -p mode=host,published=20000,target=80 nginx
xmlz7w2x89m4adyx397cko66n
overall progress: 1 out of 3 tasks 
1/3: running   [==================================================>] 
2/3: preparing [=================================>                 ] 
3/3: no suitable node (host-mode port already in use on 2 nodes) 

这个时候就创建就失败了,在mode=host模式下多个container不能同时映射同一个外部端口。(当然如果不是mode=host模式,那么多个container是可以在同一个node运行的,因为此时端口映射使用的是ingress模式,不存在多个contaienr都要往外映射端口的问题,而是swarm service统一映射端口)

这个时候就想到了另一个参数:[--mode replicated|global]

参数 [--mode replicated|global]

(这个参数是最外层的参数,不是前面--publish的那个mode参数)

  • --mode=replicated是缺省选项,表示要创建的container的数量由参数--replicas决定(缺省值为1)
  • --mode=global,表示根据swarm的node个数,在每一个node上创建并且只创建一个container,即contaienr和node是一一对应关系。

自然用了--mode=global就不能使用--replicas参数了:

$ docker service create --name mynginx --mode global --replicas=1 -p published=20000,target=80 nginx
replicas can only be used with replicated mode

哪怕参数replicas=1也不行,因为--mode global自动为service在每一个swarm节点上创建一个container,不需要指定--replicas参数了。

所以总的来说,如果指定--publish mode=host,..., 可以指定参数--mode global,就会为每一个node上创建一个container,就不存在端口冲突的问题了。

publish如何指定多个端口段

如果端口个数少,可以使用多个--publish例如:
docker service create --name mynginx -p 1000:1000 -p 1001:1001 -p 1002:1002 <image>

如果端口很多例如1000个,那该怎么办呢?也可以用端口段:

$ docker service create --name mynginx -p 5000-5999:1000-1999 nginx
wo6czxdbveut07ndjlqbr36w4
overall progress: 1 out of 1 tasks 
1/1: running   [==================================================>] 
verify: Service converged 

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
wo6czxdbveut        mynginx             replicated          1/1                 nginx:latest        *:5000-5999->1000-1999/tcp

注意的是此时不能使用长格式,只能使用这种短格式:

$ docker service create --name mynginx -p published=5000-5999,target=1000-1999 nginx
invalid argument "published=5000-5999,target=1000-1999" for "-p, --publish" flag: strconv.ParseUint: parsing "5000-5999": invalid syntax
See 'docker service create --help'.

长格式语法不识别。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值