Docker网络
查看容器的IP地址
# 第一种方法,使用docker inspect
[root@docker ~]# docker run -d --name nginx nginx
[root@docker ~]# docker inspect --format '{{.NetworkSettings.IPAddress}}' nginx
172.17.0.3
# 第二种方法,使用docker exec在容器内部执行命令获得容器IP地址
[root@docker ~]# docker exec -it nginx /bin/sh
# cat /etc/hosts
172.17.0.3 9b6cdc818311
# 第三种方法,使用docker exec在容器内部执行命令获得容器IP地址
[root@docker ~]# docker run -it flask ip addr|grep global
inet 172.17.0.4/16 scope global eth0
将容器端口暴露在主机上
- 可以通过docker run命令的-P|-p选项将容器内的端口动态绑定到宿主机上
# 这种方式不能从宿主机之外访问该应用
[root@docker opt]# cat Dockerfile
FROM python
RUN pip install flask
COPY hello.py /tmp/hello.py
CMD ["python","/tmp/hello.py"]
[root@docker opt]# docker build -t flask .
[root@docker opt]# docker inspect -f '{{.NetworkSettings.IPAddress}}' flask
Template parsing error: template: :1:18: executing "" at <.NetworkSettings.IPA...>: map has no entry for key "NetworkSettings"
[root@docker opt]# docker inspect -f '{{.NetworkSettings.IPAddress}}' foobar
172.17.0.4
[root@docker opt]# curl 172.17.0.4:5000/hi
Hello World!
# 开启端口映射
[root@docker opt]# docker kill foobar
foobar
[root@docker opt]# docker rm foobar
foobar
[root@docker opt]# docker run -d -p 5000 --name foobar flask
80891b6e5ac1ae093aacad5405655d3ca97dacfdc707260a0ea279ab402a171a
[root@docker opt]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
80891b6e5ac1 flask "python /tmp/hello.py" 3 seconds ago Up 2 seconds 0.0.0.0:4000->5000/tcp foobar
# 使用docker port查看端口映射
[root@docker opt]# docker port foobar
5000/tcp -> 0.0.0.0:4000
[root@docker opt]# docker port foobar 5000
0.0.0.0:4000
[root@docker opt]# curl localhost:4000/hi
Hello World!
- 暴露多个端口:
docker run -d -p 5000/tcp -p 53/udp flask
- 端口映射通过两种机制实现
- 首先,默认情况下Docker会修改宿主机的iptables规则.在Flask应用运行时查看iptables规则,发现在Docker链表中新增加了一条规则
[root@docker opt]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER-ISOLATION all -- anywhere anywhere
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.17.0.2 tcp dpt:commplex-main
ACCEPT tcp -- anywhere 172.17.0.4 tcp dpt:commplex-main
Chain DOCKER-ISOLATION (1 references)
target prot opt source destination
RETURN all -- anywhere anywhere
- 其次,Docker会在宿主机上启动一个轻量的代理程序.这个进程监听宿主机的所有网络接口,监听端口是为容器动态分配的端口.
[root@docker opt]# ps -ef|grep docker-proxy
root 25623 1 1 11:27 ? 00:02:54 /usr/bin/dockerd-current --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd --userland-proxy-path=/usr/libexec/docker/docker-proxy-current --init-path=/usr/libexec/docker/docker-init-current --seccomp-profile=/etc/docker/seccomp.json --selinux-enabled --log-driver=journald --signature-verification=false --storage-driver overlay2
root 26095 25623 0 14:49 ? 00:00:00 /usr/libexec/docker/docker-proxy-current -proto tcp -host-ip 0.0.0.0 -host-port 5000 -container-ip 172.17.0.2 -container-port 5000
root 28280 25623 0 15:52 ? 00:00:00 /usr/libexec/docker/docker-proxy-current -proto tcp -host-ip 0.0.0.0 -host-port 4000 -container-ip 172.17.0.4 -container-port 5000
在Docker中进行容器链接
- 当构建一个由多个服务构成的分布式应用时,需要一种机制来发现这些服务的位置,这样系统中的各个组件才能互相通信.可以手动配置IP地址,但考虑到可扩展性,需要一种自发现机制
- 使用docker run --link选项来实现
--link <container_name>:<alias>
- 案例
[root@docker opt]# docker run -d --name database -e MYSQL_ROOT_PASSWORD=root mysql
73950774914d646f9a77f8554686041732dbf07cc4f6fd2b5df8ec7bf6c0582d
[root@docker opt]# docker run -d --link database:db --name web runseb/hostname
0c59b684138e0266c491153dde7a3646003d9f8176c21a21131f114f07cddd0e
[root@docker opt]# docker run -d --link web:application --name lb nginx
a02783880a27a3702e5ae1f7aa1c2335e2f93e311ce7026a77602e5a22628479
[root@docker opt]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a02783880a27 nginx "nginx -g 'daemon ..." 5 seconds ago Up 4 seconds 80/tcp lb
0c59b684138e runseb/hostname "python /tmp/hello.py" About a minute ago Up 59 seconds 5000/tcp web
73950774914d mysql "docker-entrypoint..." 3 minutes ago Up 3 minutes 3306/tcp, 33060/tcp database
[root@docker opt]# docker inspect -f '{{.NetworkSettings.IPAddress}}' lb
172.17.0.7
[root@docker opt]# docker inspect -f '{{.NetworkSettings.IPAddress}}' web
172.17.0.6
[root@docker opt]# docker inspect -f '{{.NetworkSettings.IPAddress}}' database
172.17.0.5
[root@docker opt]# docker exec -it web env|grep DB
DB_PORT=tcp://172.17.0.5:3306
DB_PORT_3306_TCP=tcp://172.17.0.5:3306
DB_PORT_3306_TCP_ADDR=172.17.0.5
DB_PORT_3306_TCP_PORT=3306
DB_PORT_3306_TCP_PROTO=tcp
DB_PORT_33060_TCP=tcp://172.17.0.5:33060
DB_PORT_33060_TCP_ADDR=172.17.0.5
DB_PORT_33060_TCP_PORT=33060
DB_PORT_33060_TCP_PROTO=tcp
DB_NAME=/web/db
DB_ENV_MYSQL_ROOT_PASSWORD=root
DB_ENV_GOSU_VERSION=1.12
DB_ENV_MYSQL_MAJOR=8.0
DB_ENV_MYSQL_VERSION=8.0.20-1debian10
[root@docker opt]# docker exec -it lb env|grep APPLICATION
APPLICATION_PORT=tcp://172.17.0.6:5000
APPLICATION_PORT_5000_TCP=tcp://172.17.0.6:5000
APPLICATION_PORT_5000_TCP_ADDR=172.17.0.6
APPLICATION_PORT_5000_TCP_PORT=5000
APPLICATION_PORT_5000_TCP_PROTO=tcp
APPLICATION_NAME=/lb/application
# 可以通过这些环境变量来动态配置应用程序和负载均衡
- 在/etc/hosts文件中也包含了IP地址信息
[root@docker opt]# docker exec -it lb cat /etc/hosts
172.17.0.6 application 0c59b684138e web
172.17.0.7 a02783880a27
[root@docker opt]# docker exec -it database cat /etc/hosts
172.17.0.5 73950774914d
[root@docker opt]# docker exec -it web cat /etc/hosts
172.17.0.5 db 73950774914d database
172.17.0.6 0c59b684138e
- 如果重启了一个容器,那么链接了这个容器的/etc/hosts文件会自动更新,而其他环境变量保持不变.推荐使用/etc/hosts所链接的容器进行IP地址解析
- 在/etc/hosts文件中看到为链接指定的别名(alias),为容器链接添加的环境变量也会以这个别名为前缀
- 在容器运行中,可以使用inspect查看容器使用了哪些容器链接
[root@docker opt]# docker inspect -f "{{.HostConfig.Links}}" web
[/database:/web/db]
[root@docker opt]# docker inspect -f "{{.HostConfig.Links}}" lb
[/web:/lb/application]
Docker容器网络
- 在默认安装情况下,Docker会在宿主机上创建一个名为docker0的Linux网络设备.该网桥设备拥有一个私有网络地址及其所属子网.分配给docker0的子网地址为172.[17-31].42.1/16、10.[0-255].42.1/16和192.168.[42-44].1/24中第一个没有被占用的子网地址.因此,很多时候docker0的网桥设备的地址都是172.17.0.1.所有容器都会连接到该网桥设备上,并从中分配一个位于子网172.17.42.0/24中的IP地址.容器链接到网桥的网络接口会把docker0网络设备作为网关.创建新容器时,Docker会创建一对网络设备接口,并将它们放到两个独立的网络命名空间:一个网络设备放到容器的网络命名空间(eth0);另一个网络设备放到宿主机的网络命名空间,并连接到docker0网桥设备上
# 进入容器查看容器内的网络信息
# 这个容器拥有一个在172.17.0.0/16网段的IP地址,以及一个虚拟网络接口,这个网络接口是Docker创建容器时自动创建并连接到桥接设备的
[root@docker opt]# docker exec -it web /bin/sh
# ip a
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
111: eth0@if112: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:06 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.6/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:6/64 scope link
valid_lft forever preferred_lft forever
# ping 172.17.0.1
# ping docker0的IP地址(即网关)有数据包返回
PING 172.17.0.1 (172.17.0.1) 56(84) bytes of data.
64 bytes from 172.17.0.1: icmp_seq=1 ttl=64 time=109 ms
# ping 172.17.0.4
# ping另外一个容器
PING 172.17.0.4 (172.17.0.4) 56(84) bytes of data.
64 bytes from 172.17.0.4: icmp_seq=1 ttl=64 time=0.161 ms
# 查看宿主机的网络信息
[root@docker opt]# ip addr
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ff:55:a2:9a brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:ffff:fe55:a29a/64 scope link
valid_lft forever preferred_lft forever
112: veth21143bc@if111: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether fa:a8:39:49:12:72 brd ff:ff:ff:ff:ff:ff link-netnsid 4
inet6 fe80::f8a8:39ff:fe49:1272/64 scope link
valid_lft forever preferred_lft forever
发现容器中的网卡设备eth0@if112与docker0中的veth21143bif111进行了绑定.
112: veth21143bc@if111和111: eth0@if112组成一对
容器网络模式
- 通过--net=none启动一个不带任何网络功能的容器
- 如果需要使用网络,则需要手动配置
[root@docker opt]# docker run -it --rm --net=none ubuntu:update bash
root@cd93b8ac07cd:/# ip a
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
- 通过--net=host启动一个host模式容器
- 查看容器中的网络设备,与宿主机完全相同,包括docker0网络设备.容器中的进程被隔离在它自己的命名空间,它的资源被cgroups限制,容器的网络命名空间和宿主是相同的.也可以发现,容器中的主机名和宿主机是相同的
- 注意:如果是host模式,则不能在容器中对网络重新做任何修改
- host模式适用于对网络I/O性能特别敏感的进程
[root@docker opt]# docker run -it --rm --net=host ubuntu:update bash
root@docker:/# ip a
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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:fb:60:26 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.180/24 brd 10.0.0.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::8969:d6e:8d5f:998f/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:fb:60:30 brd ff:ff:ff:ff:ff:ff
inet 172.16.1.180/16 brd 172.16.255.255 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::b3b5:51c9:b323:754f/64 scope link
valid_lft forever preferred_lft forever
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ff:55:a2:9a brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:ffff:fe55:a29a/64 scope link
valid_lft forever preferred_lft forever
112: veth21143bc@if111: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether fa:a8:39:49:12:72 brd ff:ff:ff:ff:ff:ff
inet6 fe80::f8a8:39ff:fe49:1272/64 scope link
valid_lft forever preferred_lft forever
- 与启动的容器共享一个网络命名空间
# 先启动一个容器并将其主机名修改为cookbook
[root@docker opt]# docker run -it --rm -h cookbook ubuntu:update bash
root@cookbook:/# ip a
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
125: eth0@if126: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.5/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:5/64 scope link
valid_lft forever preferred_lft forever
# 启动第二个容器,适用--net=container:CONTAINER_OR_ID
[root@docker ~]# docker run -it --rm --net=container:optimistic_hypatia ubuntu:update bash
root@cookbook:/# ip a
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
125: eth0@if126: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.5/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:5/64 scope link
valid_lft forever preferred_lft forever
- 发现两个容器的主机名相同,也拥有相同的IP.在每个容器中的进程是隔离的,存在于自己的进程命名空间中,但是它们共享同一命名空间,并可以通过回环设备进行通信
配置Docker守护进程iptables和IP转发设置
- 对Docker主机上容器之间以及容器与外部网络之间的网络流量进行更精细的控制
- 在启动Docker进程时通过--ip-forward=false和--iptables=false参数对Docker的网络进行定制
- 修改Docker的默认网络设置,需要停止Docker进程
vim /etc/sysconfig/docker-network
DOCKER_NETWORK_OPTIONS=\"--iptables=false --ip-forward=false\"
systemctl restart docker
- 在这种配置下,经过Docker网桥docker0的通信流量都不会被转发到容器的网络接口上,也不会添加postrouting和masquerading规则.这意味着所有来自容器对外部的网络访问请求都会被丢弃
- 如果启用了Docker守护进程的--iptables=false标志,就不能再对容器之间的通信进行限制(即使用--icc=false),这时Docker已经不能对iptables规则进行管理.意味着,所有连接到统一Docker网桥设备的容器都可以使用任何端口进行通信
- 默认情况下,Docker守护进程可以对宿主机上的iptables规则进行修改.也就是说,Docker可以添加用于限制容器之间网络通信的iptables规则,以实现容器之间的网络隔离.如果禁止了Docker对iptables规则的修改,它将不能添加用于限制容器间通信的规则.
- 如果允许Docker去修改iptables规则,可以为Docker守护进程添加--icc=false选项.这将会为Docker网桥上的数据包添加一个默认丢弃的规则,容器之间也不能相互访问
- 修改Docker配置文件,添加--icc=false.重启Docker守护进程再启动两个容器,发现这两个容器之间互相是ping不通的
- 通过创建一个专用iptables规则可以实现互相通信
iptables -A DOCKER -p icmp --icmp-type echo-request -j ACCEPT
iptables -A DOCKER -p icmp --icmp-type echo-reply -j ACCEPT
通过Pipework理解容器网络
git clone https://github.com/jpetazzo/pipework.git
cp pipework/pipework /usr/local/bin/
docker run -itd --net=none --name cookbook ubuntu
pipework br0 cookbook 192.168.1.10/24@192.168.1.254
- 这条命令完成了下面的工作
- 在宿主机上创建网桥设备br0
- 分配IP地址192.168.1.254
- 在容器内部创建一个网络接口,并为其分配IP地址192.168.1.10
- 在容器内部添加路由信息,将网桥设置为默认网关
- 手动添加br0网桥设备,并为其分配IP地址192.168.1.254.使用brctl工具创建一个网桥设备,用ip名为网桥添加IP地址,启用网桥设备
# 添加br0网桥
brctl addbr br0
ip addr add 192.168.1.254/24 dev br0
ip link set dev br0 up
# 创建一个veth对foo、bar,并将foo连接到网桥br0上
ip link add foo type veth peer name bar
brctl addif br0 foo
ip link set foo up
# 对容器的网络进行配置(增加网络接口,设置路由信息),需要找到网络命名空间ID.Docker将容器的网络命名空间保存在/var/run/docker/netns.将/var/run/docker/netns链接到/var/run/netns,后者是ip命令默认查找网络命名空间的位置
cd /var/run
ln -s /var/run/docker/netns /var/run/netns
ip netns
NID=$(ip netns|grep -v "default")
# 通过ip link set netns命令将veth的另一端bar放到容器的命名空间中,并通过ip netns exec命令在该命名空间下为其设置一个名称和MAC地址
ip link set bar netns $NID
ip netns exec $NID ip link set dev bar name eth1
ip netns exec $NID ip link set dev eth1 address 12:34:56:78:9a:bc
ip netns exec $NID ip link set dev eth1 up
# 为eth1设备分配一个IP地址,并设置一个默认路由,这样容器就可以通过网络连接到Docker宿主机及外部网络
ip netns exec $NID ip addr add 192.168.1.1/24 dev eth1
ip netns exec $NID ip route add default via 192.168.1.254
# 访问外部网络,需添加iptables规则
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j MASQUERADE
- 创建br0网桥设备和一对veth
- 将bar放置到容器网络命名空间并进行设置
- 设置iptables
定制Docker网桥设备
- 创建自己的Docker网桥设备,取代Docker默认的网桥
[root@localhost ~]# ip link set docker0 down
[root@localhost ~]# brctl delbr docker0
[root@localhost ~]# brctl addbr cookbook
[root@localhost ~]# ip link set cookbook up
[root@localhost ~]# ip addr add 172.18.0.1/24 dev cookbook
# 编辑/etc/docker/daemon.json
[root@localhost ~]# cat /etc/docker/daemon.json
{
"bridge": "cookbook"
}
[root@localhost ~]# systemctl restart docker
# 发现docker0不再生成了,保留了创建的cookbook设备
[root@localhost ~]# ip a
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 pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:bc:97:88 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.207/24 brd 10.0.0.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::b8e0:cded:8399:825b/64 scope link noprefixroute
valid_lft forever preferred_lft forever
7: cookbook: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
link/ether 4a:63:1b:c4:ca:2d brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/24 scope global cookbook
valid_lft forever preferred_lft forever
inet6 fe80::4863:1bff:fec4:ca2d/64 scope link
valid_lft forever preferred_lft forever
[root@localhost ~]# docker run -itd --name centos centos:7.6.1810
36869dd85e37663bdf2d0f148cfa3a7801ded483d7205a5b93623896ef99f77a
[root@localhost ~]# docker inspect -f {{.State.Pid}} centos
11144
[root@localhost ~]# docker inspect -f {{.NetworkSettings.IPAddress}} centos
172.18.0.2 # 生成的IP地址是172.18.0.0网段的
尽管可以手动完成以上操作,但是创建的cookbook网桥与默认的docker0设备没有什么差别
如果想修改Docker容器默认网络模式(网桥)启动时所分配的IP地址范围,可以使用--bip选项.也可以使用--fixed-cidr来限制IP范围.或者视同--mtu选项来设置MTU大小
在Docker主机间创建GRE隧道
- host1的IP地址为192.168.33.11.网桥docker0分配的IP地址是172.17.0.1,并创建一个GRE隧道端点,其IP地址是172.17.0.2.Docker会为在该主机上启动的容器分配一个位于172.17.0.0/17网络中的IP地址
- host2的IP地址为192.168.33.12.网桥docker0分配的IP地址是172.17.128.1,并创建一个GRE隧道端点,其IP地址是172.17.128.2.Docker会为在该主机上启动的容器分配一个位于172.17.128.0/17网络中的IP地址
- 将一个/16位的网络分割为两个/17位的网络,并将这两个子网分配给不同的主机,确保两台主机上的容器不会出现IP冲突问题
# host1主机配置
systemctl stop docker
ip link set docker0 down
ip link del docker0
# 创建一个名为foo的隧道
ip tunnel add foo mode gre local 192.168.33.11 remote 192.168.33.12
# 激活foo隧道并分配一个IP地址
ip link set foo up
ip addr add 172.17.127.254 dev foo
# 添加路由信息,让所有发送到172.17.128.0/17的网络流量都经过该隧道
ip route add 172.17.128.0/17 dev foo
# host2主机配置
systemctl stop docker
ip link set docker0 down
ip link del docker0
# 创建一个名为bar的隧道
ip tunnel add bar mode gre local 192.168.33.12 remote 192.168.33.11
# 激活bar隧道并分配一个IP地址
ip link set bar up
ip addr add 172.17.255.254 dev bar
# 添加路由信息,让所有发送到172.17.0.0/17的网络流量都经过该隧道
ip route add 172.17.0.0/17 dev bar
# 设置--bip和fixed-cidr
--bip=172.17.0.1 --fixed-cidr=172.17.0.0/17
--bip=172.17.128.1 --fixed-cidr=172.17.128.0/17
- 由于Docker将会打开IP转发功能,所有经过Docker0的通信流量将会被转发到foo和bar,因此不需要将任何隧道的其中一段连接到网桥设备上
Docker网络命名空间
# 启动一个容器
[root@docker ~]# docker run -itd --name test ubuntu:update
7a3a9b75d9fd8132d6b292e8e2a8e162c7a7aab43b931337239057cf23183b5b
# 查看容器的网络命名空间
[root@docker ~]# docker inspect -f '{{.NetworkSettings.SandboxID}}' 7a3
c7945d03a82c5a7ac9e49ab0983af8568477e7193919ff3ac4846c9b41f5160b
[root@docker ~]# ls /var/run/docker/
libcontainerd/ libnetwork/ netns/ plugins/ swarm/
[root@docker ~]# ls /var/run/docker/netns/
c7945d03a82c