容器网络管理
一、docker网络管理基础
123
1、docker0虚拟交换机
- 查看网络的三个模式
[root@docker ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
a74543c7bde1 bridge bridge local
138cedd6c719 host host local
51ca74dae4e4 none null local
# 这个bridge就是对应的docker0网桥
- 创建一个容器的时候,默认使用的是桥接网络
# docker0 这个网络就是一个虚拟交换机(虚拟网桥),创建的容器都是在这个网段的里面的,也可以自己创建一个网络
[root@docker ~]# ifconfig docker0
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:83ff:fefa:a9 prefixlen 64 scopeid 0x20<link>
ether 02:42:83:fa:00:a9 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 5 bytes 526 (526.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
2、docker0网桥和容器接口关系
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
92f75978bf49 nginx "/docker-entrypoint.…" 28 hours ago Up 3 minutes 0.0.0.0:8080->80/tcp, :::8080->80/tcp web
[root@docker ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02422f40f62f no veth87c6d05
-
创建一个容器后,docker0虚拟交换机上面会有一个接口连接着,然后这个接口也连接着容器,因此就能通信了
-
创建一个容器后,就会生成一对veth虚拟接口,也就是多了一根线,一边连接着docker0网桥,一边连接着容器

[root@docker ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02422f40f62f no vethe07dc3e
[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: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:a5:d5:eb brd ff:ff:ff:ff:ff:ff
altname enp3s0
inet 192.168.200.10/24 brd 192.168.200.255 scope global noprefixroute ens160
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fea5:d5eb/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:2f:40:f6:2f 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:2fff:fe40:f62f/64 scope link
valid_lft forever preferred_lft forever
7: vethe07dc3e@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 6e:d0:54:81:83:10 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::6cd0:54ff:fe81:8310/64 scope link
valid_lft forever preferred_lft forever
# docker0交换机上连接一个7号口,这个7号口又连接这个6号口
# 进入容器里面查看,连接的就是容器的网卡
[root@docker ~]# docker exec -ti web /bin/sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
# 然而这个容器的网卡又连接这个7号口
# 也就是说这相当于是一个数据线,连接着docker0网桥和容器网卡
- 这个docker0网桥又通过nat转发到主机的ens160网卡,ens160连接这个vmnet8,再次通过nat转发出去,实现访问外网的功能
二、三种网络模式
1、host模式(主机模式)
- 会复制主机的所有网络,使用的是主机的ip地址
# 创建一个主机网络的容器,使用的主机的ip地址
[root@docker /]# docker run -tid --name q3 --network host alpine
6ea0b73fcba14c0cc5889d556f86b1ee8011e13b3dd0a4890e72a17e4d19e28a
[root@docker /]# docker exec -ti q3 /bin/sh
/ # ifconfig
br-a25b80614af0 Link encap:Ethernet HWaddr 02:42:82:83:53:6A
inet addr:192.111.10.1 Bcast:192.111.10.255 Mask:255.255.255.0
inet6 addr: fe80::42:82ff:fe83:536a/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:11 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:328 (328.0 B) TX bytes:1036 (1.0 KiB)
docker0 Link encap:Ethernet HWaddr 02:42:2F:40:F6:2F
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
inet6 addr: fe80::42:2fff:fe40:f62f/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:3040 errors:0 dropped:0 overruns:0 frame:0
TX packets:2988 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3525318 (3.3 MiB) TX bytes:3056627 (2.9 MiB)
ens160 Link encap:Ethernet HWaddr 00:0C:29:A5:D5:EB
inet addr:192.168.200.10 Bcast:192.168.200.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fea5:d5eb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:27354 errors:0 dropped:0 overruns:0 frame:0
TX packets:15130 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:19736683 (18.8 MiB) TX bytes:5550775 (5.2 MiB)
2、桥接模式
-
创建容器没有指定网络,默认使用的就是桥接模式
-
可以自定义桥接网络,创建一个桥接网络
-
也就相当于是创建了一个虚拟网桥(交换机)
-
docker0网桥和自定义网桥,是不同网段的,如果想要这2个网段通信的话,需要配置路由条目
# 相当于又创建了一个虚拟网桥(交换机)
[root@docker /]# docker network create --subnet 192.111.10.0/24 b1
a25b80614af0faf9243353e6a03207a3292b6ccc1a42f34ee8202a32245dec5d
[root@docker /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
a25b80614af0 b1 bridge local
ef2509790e01 bridge bridge local
138cedd6c719 host host local
51ca74dae4e4 none null local
[root@docker /]# ifconfig
br-a25b80614af0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 192.111.10.1 netmask 255.255.255.0 broadcast 192.111.10.255
ether 02:42:82:83:53:6a txqueuelen 0 (Ethernet)
RX packets 1138 bytes 610080 (595.7 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1202 bytes 1297480 (1.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:2fff:fe40:f62f prefixlen 64 scopeid 0x20<link>
ether 02:42:2f:40:f6:2f txqueuelen 0 (Ethernet)
RX packets 3040 bytes 3525318 (3.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2988 bytes 3056627 (2.9 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
# 创建一个容器连接b1网桥
root@docker /]# docker run -tid --name b123 --network b1 alpine
a6494b831b24da9f980f838ff8efce590bf88ac30403d8749233a76435dcf874
[root@docker /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a6494b831b24 alpine "/bin/sh" 2 seconds ago Up 1 second b123
# 登录容器里面访问外网
[root@docker /]# docker exec -ti b123 /bin/sh
/ # ping qq.com
PING qq.com (203.205.254.157): 56 data bytes
64 bytes from 203.205.254.157: seq=0 ttl=127 time=173.330 ms
三、实验
1、搭建服务
-
通过容器互联搭建一个wordpress
-
wordpress是要连接到数据上的
-
需要wordpress和mysql镜像
-
创建一个mysql容器后,数据是存放在哪里呢,如果容器被删除的话,数据也会被删除吗
-
这个时候就需要-v 数据映射
-
创建wordpress容器,需要指定数据库,对接数据库
WORDPRESS_DB_HOST # 博客系统要连接到哪台主机上(db所在的容器上)
WORDPRESS_DB_USER # 博客系统要使用哪个榕湖对接
WORDPRESS_DB_PASSWORD # 它的密码是什么
WORDPRESS_DB_NAME # 使用哪个数据
docker run -tid --name db --restart always -v /db:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=wordpress mysql
# 连接数据库主机使用的ip地址,后面实验ip地址会发生变化怎么办呢
docker run -tid --name blog -v /web:/var/www/html/ -p 80:80 -e WORDPRESS_DB_HOST=172.17.0.3 -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=root -e WORDPRESS_DB_NAME=wordpress wordpress

-
访问到界面,就能说这个wordpress镜像和数据服务是正确的
-
如果还需要输入用户名或者密码,主机等信息,就说明db容器是错误的
2、问题
-
删除db容器,wordpress页面会出现错误,但是了数据文件都保存下来了,因此,可以再次创建db容器
-
但是呢,还是有问题,就是再次创建db容器的ip会发生变化
-
因此有一个方法,就是创建博客容器的时候,使用链接,而不是使用ip地址,使用link 链接
-
以后blog容器就通过别名来进行访问了,
3、解决方法
- --link选项
# 用法
# a容器是数据库,b容器是网站服务,b容器需要连接a容器
# 创建b容器时,建立一个--link a:a容器别名,之后就是通过这个别名来进行访问的a容器,因此,a容器的ip地址发生变化不影响
--link a容器:a容器别名
- 改进版
[root@docker /]# docker run -tid --name db --restart always -v /db:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=wordpress mysql
[root@docker /]# docker run -tid --name blog -v /web:/var/www/html/ -p 80:80 --link db:dbbm -e WORDPRESS_DB_HOST=dbbm -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=root -e WORDPRESS_DB_NAME=wordpress wordpress
73291467b5f05eceebe029d6086841cf97242d5b89f16cbd587c56d5fbb14ced
-
因此的话,再次删除这个db容器,创建一个db容器,就能回复正常了,前提,名字不能变,数据的文件都存储在
-
又出现了一个问题,删除了db容器后,随便创建一个容器,再次创建db容器,发现还是不行,这个时候重启docker服务,重启blog容器就恢复正常了
-
使用了link的话,尽量不要删除,stop关闭db容器即可
# 关闭容器即可,删除容器不行
# 关闭db容器,创建一个别的容器,再次启动db容器,blog容器内的ip地址会发生变化
root@docker /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5d67b2274842 wordpress "docker-entrypoint.s…" 10 seconds ago Up 9 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp blog
ea2295a68980 mysql "docker-entrypoint.s…" 21 seconds ago Up 20 seconds 3306/tcp, 33060/tcp db
[root@docker /]# docker exec -ti blog /bin/bash
root@5d67b2274842:/var/www/html# 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.2 dbbm ea2295a68980 db
172.17.0.3 5d67b2274842
# 关闭db容器,创建一个新的容器,占用ip地址
[root@docker ~]# docker inspect db | grep -i ipaddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
"IPAddress": "172.17.0.2",
[root@docker ~]# docker stop db
do^Hdb
[root@docker ~]# docker run -tid --name q1 alpine
b973b2901f1239189d52b1f92cd0536263277ace82d8d416aeef7a7061ee13c0
[root@docker ~]# docker start db
db
[root@docker ~]# docker inspect db | grep -i ipaddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.4",
"IPAddress": "172.17.0.4",
# blog里面的ip地址发生了变化
root@5d67b2274842:/var/www/html# 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.4 dbbm ea2295a68980 db
172.17.0.3 5d67b2274842
# 这样就能进行访问了,尽量不要删除
4、link不便
-
方法不常用,为了避免底层数据库ip地址发生变化,导致上层的应用无法访问,可以使用link指定一个别名
-
link是单向的,一但db的ip地址发生变化,上层的应用地址是无法跟着变化的,需要重新创建
问题
-
docker单节点,同网段通信
-
docker0网桥和自定义网桥,是不同网段的,如果想要这2个网段通信的话,需要配置路由条目

浙公网安备 33010602011771号