我的试验环境说明:centos8.4 + Docker version 20.10.7, build f0df350
如何让容器之间能互相通信呢?答案就是《容器互联》。
参考:
https://www.cnblogs.com/kevingrace/p/6590319.html
https://www.cnblogs.com/bakari/p/9036984.html
Docker单主机容器通信
基于对net namespace的控制,docker可以为在容器创建隔离的网络环境,在隔离的网络环境下,容器具有完全独立的网络栈,与宿主机隔离,也可以使容器共享主机或者其他容器的网络命名空间,基本可以满足开发者在各种场景下的需要。
按docker官方的说法,docker容器的网络有五种模式:
bridge模式,–net=bridge(默认)
这是dokcer网络的默认设置,为容器创建独立的网络命名空间,容器具有独立的网卡等所有单独的网络栈,是最常用的使用方式。在docker run启动容器的时候,如果不加–net参数,就默认采用这种网络模式。安装完docker,系统会自动添加一个供docker使用的网桥docker0,我们创建一个新的容器时,容器通过DHCP获取一个与docker0同网段的IP地址,并默认连接到docker0网桥,以此实现容器与宿主机的网络互通。
host模式,–net=host
这个模式下创建出来的容器,直接使用容器宿主机的网络命名空间。将不拥有自己独立的Network Namespace,即没有独立的网络环境。它使用宿主机的ip和端口。这种模式主要适用于管理员希望以docker方式管理服务器。(实际使用不多)
none模式,–net=none
为容器创建独立网络命名空间,但不为它做任何网络配置,容器中只有lo,用户可以在此基础上,对容器网络做任意定制。这个模式下,dokcer不为容器进行任何网络配置。需要我们自己为容器添加网卡,配置IP。因此,若想使用pipework配置docker容器的ip地址,必须要在none模式下才可以。
其他容器模式(即container模式,join模式),–net=container:NAME_or_ID
与host模式类似,只是容器将与指定的容器共享网络命名空间。这个模式就是指定一个已有的容器,共享该容器的IP和端口。除了网络方面两个容器共享,其他的如文件系统,进程等还是隔离开的。
用户自定义:docker 1.9版本以后新增的特性,允许容器使用第三方的网络实现或者创建单独的bridge网络,提供网络隔离能力。
参考:https://www.coonote.com/docker-note/docker-network-mode.html
最后发现默认的docker0这种bridge和用户自己创建的bridge的网络方案最实用。那么这两种方式有啥区别呢?
Link方式实现本机容器间互联通信
容器互联大体有以下三种方式:
- 基于volume的互联
- 基于link的互联
- 基于网络的互联
一些常用命令:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
docker network ls
docker network create -d bridge demo-net # 新建虚拟网络
# 用下面的命令创建docker网桥
docker network create br0 -d bridge -o com.docker.network.bridge.name='br0' \
--subnet=172.10.200.0/24 --ip-range=172.10.200.0/24 --gateway=172.10.200.1
# 运行容器
docker run -itd --name centostst --network br0 bmc/opensuse15.2:dev /bin/bash
# 第二个例子
docker run -itd --name suse11 --network demo-net opensuse /bin/bash
docker run -itd --name suse22 --network demo-net opensuse /bin/bash
# 分别进入容器,户型能够ping通
docker exec -it suse11 /bin/bash
docker exec -it suse22 /bin/bash
# vi /etc/docker/daemon.json 设置所有容器的DNS
# 这样容器就可以共享这里的DNS配置,解析域名了。
"dns": [
"223.5.5.5",
"8.8.8.8"
]
# 单独指定容器DNS
docker run -it --rm --dns=223.5.5.5 --dns-search=test.com bmc/opensuse15.2:dev
|
添加路由实现容器跨主机互联通信
Docker默认的网桥是docker0。此网桥只会在本机连接所有容器。下面我们借助两台服务器上的docker0网桥来互相通信。
1
2
3
4
5
6
7
|
vi /etc/docker/daemon.json
{
"bip":"172.16.200.1/24"
}
{
"bip":"172.16.201.1/24"
}
|
上面的配置分别配置两台服务器,然后重启docker。
之后你会发现现在两台机器上的两个容器IP是不会互通的。但是他们能够Ping通主机的内网IP,下面在宿主机上面添加到达对方的路由:
1
2
3
4
5
6
7
8
9
|
# docker1
route add -net 172.16.201.0/24 gw 10.10.200.172
route del -net 172.16.201.0/24 gw 10.10.200.172
# docker2
route add -net 172.16.200.0/24 gw 10.10.200.142
# 添加权限
--privileged
|
杯具,最后发现还是不通,看看是哪里出问题了? (这种方式并不是太好,还是用下面的方式吧 O(∩_∩)O哈哈~)
桥接到Docker宿主机实现跨主机Docker容器通信
如果希望Docker跨主机访问,最简单的方式就是将不同主机的docker0 设置为同一网段。
整体网络拓扑结构就是这样(网上借用的示意图,参考即可):
在两台宿主机,安装网桥查询工具
1
2
3
4
5
|
zypper in bridge-utils
brctl show
PC-A: eth1:10.10.200.142
PC-B: eth1:10.10.200.172
|
PC-A执行:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# 第一步
vi /etc/docker/daemon.json
"bip": "10.10.200.142/24",
"fixed-cidr": "10.10.200.16/28"
"default-gateway": "192.168.61.1" # 不需要这行
# 第二步
ifconfig eth1 0.0.0.0 # 将物理网卡IP值空
brctl addif docker0 eth1 # 将docker0 桥接到 eth1 上
brctl show
systemctl restart docker.service
ifconfig # 查看网卡
docker0 Link encap:Ethernet HWaddr 02:42:6A:9E:15:CA
inet addr:10.10.200.142 Bcast:10.10.200.255 Mask:255.255.255.0
# 第三步
docker start susexx # 启动容器,查看IP,ping主机试一试
|
PC-B执行:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# 第一步
vi /etc/docker/daemon.json
"bip": "10.10.200.172/24",
"fixed-cidr": "10.10.200.32/28"
# 第二步
ifconfig eth1 0.0.0.0 # 将物理网卡IP置空
brctl addif docker0 eth1 # 将docker0 桥接到 eth1 上
brctl show
systemctl restart docker.service
ifconfig # 查看网卡
docker0 Link encap:Ethernet HWaddr 02:42:6A:9E:15:CA
inet addr:10.10.200.172 Bcast:10.10.200.255 Mask:255.255.255.0
# 第三步
docker start susexx # 启动容器,查看IP,ping主机试一试
|
大家可以看到实现了,PC-A 和 PC-B 两台宿主机上的容器互通。
参考:
https://developer.51cto.com/art/202002/609994.htm
https://www.pianshen.com/article/5546389320/
主机重启自动启动br0的绑定
在上面的配置中,如果主机重启,有可能网桥br0上配置的IP地址无法正常访问,这是因为网桥没有和实体网卡绑定。怎么办?
CentOS系统
这个时候在/etc/rc.local
中配置brctl addif br0 eno1
可能报错,重启不生效。给网卡做如下配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
# brctl addif br0 eno1
# /etc/sysconfig/network-scripts/ifcfg-br0
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
UUID=f2e0b49a-d9fe-4472-85e4-30ccdfbb254e
TYPE=Bridge
NAME=br0
DEVICE=br0
ONBOOT=yes
IPADDR=192.168.xx.xx
PREFIX=16
# /etc/sysconfig/network-scripts/ifcfg-eno1
TYPE=Ethernet
BOOTPROTO=none
ONBOOT=yes
DEVICE=eno1
BRIDGE=br0
|
SuSE系统
suse用上面的方法可能不行了,这个时候把绑定命令写入after.local
文件中有效。
1
2
3
4
5
6
7
|
# cat /etc/init.d/after.local
#!/bin/bash
brctl addif br0 em1
brctl addif br1 em2
# systemctl status after-local.service
# 启动服务的配置可以参考其它文章。
|
SSH登录到容器
参考:/2021/06/17020156-docker-qa.html
(完)