docker容器网络配置之容器间的链接(默认桥接网络下的links)

一、 遗留的容器连接方式  --link

  --link是docker 的一个遗留的特征,最终可能被删除。除非绝对需要使用,不然,建议使用 user-defined network 建立容器间的连接。不同的是,使用--link,容器间可共享变量,而使用 user-defined 网络不行,但是也通过一种更可控方式实现容器间变量共享,例如数据卷。

     本文章主要默认桥接网络下 容器间采用遗留连接特征(--link)通讯细节,并且讨论容器间的安全交互问题。随着docker 网络特征(network features)的引入,仍然可以使用 创建连接方式促进容器间交互,但是它与 默认桥接网络和自定义的桥接网络又存在不同。

     本文章首先讨论容器间端口连接问题,然后深入 讨论容器在 默认桥接网络下的连接问题。

1.1 使用网络端口映射方式连接

首先,运行一个简单的python flask 程序

[root@localhost docker]# docker run -P -d  training/webapp python app.py

     容器创建后,由于采用 -P(大写)参数,docker自动将容器内部需要开放的端口自动映射到主机上一个随机较高的短暂端口范围内的端口。我们可使用docker ps  或 docker container ls 查看

[root@localhost docker]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
a9e336610a0a        training/webapp     "python app.py"     7 seconds ago       Up 6 seconds        0.0.0.0:32768->5000/tcp   elated_hugle

可发现,将容器的5000 tcp端口映射到主机端口32768.

   也可以通过指定具体端口映射关系,例如将主机端口80映射到容器端口5000  标记  -p(小写)

[root@localhost docker]# docker run -p 80:5000 -d  training/webapp python app.py   
b9401a847804210e665e540ff8bc3e9b80863731eeb96f4aa5e0b82465834095
[root@localhost docker]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
b9401a847804        training/webapp     "python app.py"     4 seconds ago       Up 2 seconds        0.0.0.0:80->5000/tcp   affectionate_mahavira
[root@localhost docker]# 

    如此方式,智能一个容器的5000端口映射到主机,但是如此存在多个容器间该端口需要通讯,则不适用。解决方式,采用主机的一个较高临时端口范围来绑定不同容器的临时端口。

[root@localhost docker]# docker run -d -p 8000-9000:5000 --name node1 --hostname test1  training/webapp python app.py                                    
c92a9244159a569031882bc9429dbdad9b5993d99cac61128eb529103f1ff543
[root@localhost docker]# docker run -d -p 8000-9000:5000 --name node2 --hostname test2  training/webapp python app.py  
a7387aae557b039e26a13b7c0bad41b2f366283f778654efa60fdcc67697b672
[root@localhost docker]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
a7387aae557b        training/webapp     "python app.py"     2 seconds ago       Up 1 second         0.0.0.0:8001->5000/tcp   node2
c92a9244159a        training/webapp     "python app.py"     13 seconds ago      Up 12 seconds       0.0.0.0:8000->5000/tcp   node1
[root@localhost docker]# 

   如此,每个容器的5000端口,将自动映射到主机的端口范围内。

   默认情况下,使用 -p标记,是将指定端口绑定到主机所有接口(0.0.0.0)上,使用 -p另一种方式可把端口映射到本地 local host上,或者指定某个网卡上。

[root@localhost docker]# docker run -d -p 127.0.0.1:80:5000 training/webapp python app.py
37ebfc97fbf60d7cdc2b939e34fb555847395499fe00aa183a16810a118d450e
[root@localhost docker]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
37ebfc97fbf6        training/webapp     "python app.py"     10 seconds ago      Up 8 seconds        127.0.0.1:80->5000/tcp   brave_albattani

如此方式将主机 localhost 的端口80 绑定到容器端口 5000。但是和上述说的确定一样,只能存在一个容器能够绑定,可以使用动态绑定方式

[root@localhost docker]# docker run -d -p 127.0.0.1::5000 training/webapp python app.py  
d654f947c0f7ab2bfb2a70e20e9266dc598276641cc544986b4e71c899bd8753
[root@localhost docker]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                       NAMES
d654f947c0f7        training/webapp     "python app.py"     5 seconds ago       Up 3 seconds        127.0.0.1:32768->5000/tcp   trusting_noether

此时,动态端口为32768.再动态启动一个, 32769

[root@localhost docker]# docker run -d -p 127.0.0.1::5000 training/webapp python app.py
c5e7b5dfc039652d3d5545c622b38bc01637a056d8bad4fbf47e3578c3a9d612
[root@localhost docker]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                       NAMES
c5e7b5dfc039        training/webapp     "python app.py"     4 seconds ago        Up 3 seconds        127.0.0.1:32769->5000/tcp   sharp_easley
d654f947c0f7        training/webapp     "python app.py"     About a minute ago   Up About a minute   127.0.0.1:32768->5000/tcp   trusting_noether

  默认情绪下,绑定端口一般都为tcp协议,可在 -p的参数下带 /udp /tcp /sctp等方式,指定协议类型

[root@localhost docker]# docker run -d -p 127.0.0.1:82:5000/udp training/webapp python app.py
1304cc996745431dea2460a1d9c87b4549c5f29521b8aec4d9a7e001a9d0e3eb
[root@localhost docker]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                              NAMES
1304cc996745        training/webapp     "python app.py"     2 seconds ago       Up 1 second         5000/tcp, 127.0.0.1:82->5000/udp   clever_murdock

同样,可使用 docker port 指令,查看容器具体端口的映射情况 可通过容器ID 或者容器名

[root@localhost docker]# docker port node1 5000
0.0.0.0:8000

  注意:  -p 标记可重复使用,用于指定不同端口映射关系。

1.2 连接容器到链接系统

       这一章节,主要介绍,默认桥接网络模式下容器连接。网络端口映射不是容器间通讯的唯一方式,docker 还拥有一个链接系统,允许容器相互连接,并共享连接信息,当一个容器被连接,则源容器的信息将可被发送给被连接的容器。因此,被连接的容器可查看源容器的被选定数据源的各方面信息,例如变量等。

 1.2.1 命名的重要性

为建立链接系统,docker依赖容器的命名,容器在创建时,如果未指定命名,则自动给一个名字,使用 --name 标记,在启动容器时,可自定义指定容器名字。使用名字具有如下两个好处:

     (1) 便于记忆,例如一个web程序的容器,可命名为 web

       (2)    为docker 提供了一个方便的引用点,例如将容器 web 连接到 容器db

    例如启动一个名为web的容器,然后调用 docker ps , 或者docker container inspect web 查看容器具体信息

[root@localhost hadoop]# docker run -d -P --name web training/webapp python app.py
93e7d4982c5436783ad2f57270aeb73feaaa57e7273e932c5524542c0aeb967f
[root@localhost hadoop]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
93e7d4982c54        training/webapp     "python app.py"     6 seconds ago       Up 5 seconds        0.0.0.0:32769->5000/tcp   web

注意 :容器名称必须唯一,意味着一台主机的daemon 下,只能存在一个名为web的容器,如果需要重新建立一个名为web的容器,需要先删除旧的容器,这里有个建议,在启动容器时 docker  create / run  带上标记 --rm  ,  一旦容器停止,则自动删除该容器。

1.2.2 容器间沟通  --link

        链接 允许容器发现各自对方,同时构建安全的信息交互链路,当创建一个链接时,则在源容器和接收容器间创建了一条沟通渠道,接收容器可浏览源容器的部分数据信息。我们使用标记 --link ,这次我们创建一个包含数据库的容器,。

 

[root@localhost hadoop]# docker run -d --name db training/postgres
8ebe0029de23186cfd729b48c4e227be6392ad6d56f1cb53b96e9e789883ee7a
[root@localhost hadoop]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
8ebe0029de23        training/postgres   "su postgres -c '/us…"   49 seconds ago      Up 47 seconds       5432/tcp                  db
93e7d4982c54        training/webapp     "python app.py"          13 minutes ago      Up 13 minutes       0.0.0.0:32769->5000/tcp   web

我们在再把之前的容器web 删除, 然会在新建一个容器 连接db

[root@localhost hadoop]# docker container rm -f web
web
[root@localhost hadoop]# docker run -d -P --link db:db --name web training/webapp python app.py
ae71a962f945a14a1f879258e326318d374d91fe99628120d3f69d369f4ba4d5
[root@localhost hadoop]# 

    使用 --link 标记的个数   --link  <name or id>:alias     冒号左边为容器的名称或者ID  右边为  源容器的别名。

   然后我们可调用 docker inspect -f  格式查看web 容器的链接信息

[root@localhost hadoop]# docker inspect -f {{.HostConfig.Links}} web
[/db:/web/db]
[root@localhost hadoop]# 

可发现,web容器已经链接到 db容器,/web/db, 允许web容器访问db容器的部分信息,进入容器 web  打开 /etc/hosts 就可以看到db容器的信息,同时可直接ping db

[root@localhost hadoop]# docker exec -ti web /bin/bash
root@ae71a962f945:/opt/webapp# pwd
/opt/webapp
root@ae71a962f945:/opt/webapp# 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
192.168.0.3     db 8ebe0029de23
192.168.0.2     ae71a962f945
root@ae71a962f945:/opt/webapp# ping db   
PING db (192.168.0.3) 56(84) bytes of data.
64 bytes from db (192.168.0.3): icmp_seq=1 ttl=64 time=0.130 ms
64 bytes from db (192.168.0.3): icmp_seq=2 ttl=64 time=0.038 ms

         那么当我们使用 --link 建立容器间的链接时,实际进行什么操作? 我们知道,一个链接运行 源容器将自身部分信息传递给接收容器,这里接收容器是 web, 源容器是db, web可方式db的某些信息, 实际上,docker 在web容器和db容器新建一个安全通道,该通道并不需要容器对外开放任何端口。而且也不用在启动容器时,采用参数 -p  或者 -P指定容器开发端口,这就是 link的最大好处之一,不需要向容器公开通道,这里就是 PostgreSQL数据库不需要向 web公开端口。

      docker传递源容器的信息给接收容器,一般采用如下两种方式:

             (1)    环境变量

          (2) 更新/etc/hosts  文件  。  前面通过查看该文件可观察到  添加了db容器的IP地址和容器ID

1.3 环境变量

        在创建容器间的链接时,docker会创建根据 --link 的参数,创建一些环境变量,同时docker可能暴露源 容器的环境变量,那些可能被暴露源容器的环境变量来自于如下:

     (1)源容器的Dockerfile 中使用ENV 指定的环境变量

     (2)源容器在启动时,-e  或  --env 或者  --env-file  指定的环境变量

        那些带有源容器信息的环境变量,被允许在接收容器程序化发现(特定规则,下文讲到)。因此,注意,环境变量中避免存储一些敏感信息,避免被那些连接容器发现。

       docker在创建链接时,根据--link参数 为接收端容器生成一个 <alias>_NAME 的环境变量,这里指web容器,我们可进入容器内部查询。

[root@localhost hadoop]# docker exec -ti web /bin/bash
root@0af1176d2df9:/opt/webapp# echo $BACKDB_NAME
/web/backdb
root@0af1176d2df9:/opt/webapp# 

   我们使用 --link   db:backdb 将web容器链接到db容器,则在web容器新建一个环境变量 BACKDB_NAME=/web/backdb

   同样 docker 还为源容器的公开的端口新建了一些列的环境变量。以如下的规则;

    <name>_PORT_<port>_<protocol>

  每个段部分的命名与介绍:

    <name>   即为  --link 指定的别名,  例如     这里的backdb

    <port>   开放的端口

    <protocol>  TCP  或者UDP

 docker 使用这些前缀定义,定义了三个不同的环境变量:

   固定前缀 ADDR 返回源容器地址信息  例如   BACKDB_PORT_5432_TCP_ADDR =192.168.0.2

   固定前缀PORT返回源容器的开放端口信息 例如: BACKDB_PORT_5432_TCP_PORT = 5432

   固定前缀PROTO 返回源容器开放端口通讯协议: 例如: BACKDB_PORT_5432_TCP_PROTO=tcp

当有多个开放端口时,针对每个端口定义该三个变量,如果有4个开放端口,则存在12个如此规则的环境变量。

[root@localhost hadoop]# docker exec -ti web /bin/bash
root@0af1176d2df9:/opt/webapp# echo $BACKDB_PORT_5432_TCP_ADDR
192.168.0.2
root@0af1176d2df9:/opt/webapp# echo $BACKDB_PORT_5432_TCP_PORT
5432
root@0af1176d2df9:/opt/webapp# echo $BACKDB_PORT_5432_TCP_PROTO
tcp
root@0af1176d2df9:/opt/webapp# 

另外,docker 还创建一个环境变量 <alias>_PORT 返回第一个开放端口的具体信息 (包含了ip、port 、protocol)

root@0af1176d2df9:/opt/webapp# echo $BACKDB_PORT               
tcp://192.168.0.2:5432
root@0af1176d2df9:/opt/webapp# 

       最后,针对源容器的环境变量,在接收容器,将每个变量采用<alias>_ENV_<name>方式保存,并在接收容器启动时创建该些变量,例如前面,如果我们启动db容器时 带入参数 -e DBNAME="testName".   则我们在接收容器web内可查看该变量,注意alias别名前缀使用大写。

root@0af1176d2df9:/opt/webapp# echo $BACKDB_ENV_DBNAME
testName

 注意:与/etc/hosts文件中的主机条目不同,如果源容器重新启动,存储在环境变量中的IP地址不会自动更新。因此,一般使用/etc/hosts 解析源容器的IP地址信息。

       那些变量,仅为容器第一个进程设置,当一些守护经常构建时,例如sshd, 那些变量将被清除。

1.4 更新 /etc/hosts文件

     容器间创建链接后,docker自动更新接收容器的/etc/hosts文件,添加源容器的ip地址等相关信息到条目中,源容器的/etc/hosts未保存接收容器的信息。

root@0af1176d2df9:/opt/webapp# 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
192.168.0.2     backdb 92aca4dce8fc db
192.168.0.3     0af1176d2df9
root@0af1176d2df9:/opt/webapp# exit
[root@localhost hadoop]# 
[root@localhost hadoop]# docker exec -ti db /bin/bash 
root@92aca4dce8fc:/# 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
192.168.0.2     92aca4dce8fc
root@92aca4dce8fc:/# 

如web容器内保存 db容器的 名称,ID和别名,web容器分别利用名称  ID和别名 均可访问到db容器

root@0af1176d2df9:/opt/webapp# 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
192.168.0.2     backdb 92aca4dce8fc db
192.168.0.3     0af1176d2df9
root@0af1176d2df9:/opt/webapp# ping db
PING backdb (192.168.0.2) 56(84) bytes of data.
64 bytes from backdb (192.168.0.2): icmp_seq=1 ttl=64 time=0.145 ms
64 bytes from backdb (192.168.0.2): icmp_seq=2 ttl=64 time=0.038 ms
64 bytes from backdb (192.168.0.2): icmp_seq=3 ttl=64 time=0.044 ms
^C
--- backdb ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.038/0.075/0.145/0.050 ms
root@0af1176d2df9:/opt/webapp# ping backdb
PING backdb (192.168.0.2) 56(84) bytes of data.
64 bytes from backdb (192.168.0.2): icmp_seq=1 ttl=64 time=0.112 ms
64 bytes from backdb (192.168.0.2): icmp_seq=2 ttl=64 time=0.037 ms
^C
--- backdb ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.037/0.074/0.112/0.038 ms
root@0af1176d2df9:/opt/webapp# ping 92aca4dce8fc
PING backdb (192.168.0.2) 56(84) bytes of data.
64 bytes from backdb (192.168.0.2): icmp_seq=1 ttl=64 time=0.053 ms
64 bytes from backdb (192.168.0.2): icmp_seq=2 ttl=64 time=0.045 ms
^C
--- backdb ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.045/0.049/0.053/0.004 ms
root@0af1176d2df9:/opt/webapp# 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.098 ms
64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.041 ms
^C
--- 192.168.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.041/0.069/0.098/0.029 ms
root@0af1176d2df9:/opt/webapp# 

一个容器可允许被多个容器同时连接,但是注意不能启动相同容器名

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值