docker 网络
环境信息
- Centos 7.9.2009
- docker-ce-19.03.15
Docker 网络模式
Bridge 模式
bridge 模式是 docker 的默认网络模式,不使用 --network
参数,就是 bridge 模式。
当 Docker 进程启动时,会在主机上创建一个名为 docker0 的虚拟网桥,默认主机上启动的 Docker 容器会连接到这个虚拟网桥上。
容器启动时,docker 会从 docker0 网桥的子网中分配一个 IP 地址给容器中的网卡。大体流程为在主机上创建一个 `veth pair`,Docker 将 veth pair
的一端放在容器中,命名为 eth0
并配置 IP,网关,路由等信息,将 veth pair
的另一端加入 docker0 网桥。
通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。
Host 模式
如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace,而是和宿主机一样在 Root Network Namespace,容器中看到的网络方面的信息和宿主机一样,容器使用的网络资源在整个 Root Network Namespace 不能出现冲突。容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口,主机名也是使用宿主机的。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
host 模式下的容器可以看到宿主机上的所有网卡信息,可以直接使用宿主机 IP 或主机名与外界通信,无需额外的 NAT,也无需通过 Linux bridge 进行转发或者数据包的封装,可以访问主机上的其他任一容器。
使用如下命令参数启动 host 网络模式的容器
docker run --network host --name test1 -p 80:80 -d -it centos:centos7.9.2009 |
host 模式的容器,没有自己的 network namespace,在 root network namespace 中。进入测试容器 test1
,查看网卡、 IP 信息及端口、主机名信息,会看到和宿主机一样的信息。
ip link |
host 模式的缺点
- 容器没有自己的
network namespace
,网络和宿主机或其他使用host
模式的容器未隔离,容易出现资源冲突,比如同一个宿主机上,使用host
模式的容器中启动的端口不能相同。
None 模式
使用 none
模式,Docker 容器拥有自己的 Network Namespace
,但是,系统并不为 Docker 容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡(lo
回环网卡除外)、IP、路由等信息。需要我们自己为 Docker 容器添加网卡、配置 IP 等。
参考以下命令创建 none
模式的容器
docker run --network none --name test-none -p 82:80 -d -it centos7:my |
容器创建后,进入容器中,查看网卡和 IP 等信息,容器中默认只存在 lo
网卡,不存在其他网卡
ip add |
以下操作演示手动为容器配置网络
创建
veth pair
ip link add veth0 type veth peer name veth0_p
将
veth pair
的一端veth0
放入 docker 默认的网桥docker0
,另一端veth0_p
放入容器中首先使用命令
docker inspect test-none | grep "Pid"
找到容器对应的 PID,此处为 84040,根据此 PID 将 veth 的一端放入容器的 network namespace 中ip link set dev veth0 master docker0
ip link set dev veth0 up
ip link set veth0_p netns 84040在宿主机上面检查
veth0
,确定其已经加入网桥docker0
,并且veth0_p
已不在root network namespace
中ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:e7:c0:27 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:f2:1b:dc:ea brd ff:ff:ff:ff:ff:ff
12: veth0@if11: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue master docker0 state LOWERLAYERDOWN mode DEFAULT group default qlen 1000
link/ether 16:7f:98:d8:9d:dc brd ff:ff:ff:ff:ff:ff link-netnsid 0重新进入容器,检查网卡信息,可以看到容器中已经有了网卡
veth0_p
,状态为DOWN
ip -d link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0 addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
11: veth0_p@if12: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether be:f1:94:9f:b8:c9 brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 0
veth addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535为容器中的网卡配置 IP 及网关等信息
为了能在宿主机对容器的
network namespace
进行操作,首先需要将容器的network namespace
暴露出来,之后可以在宿主机通过network namespace
名称(此处为 84040,可以自定义)操作network namespace
。Linux network namespace 参考ln -s /proc/84040/ns/net /var/run/netns/84040
ip netns ls
84040 (id: 0)通过
network namespace
名称(此处为 84040)配置容器中网卡的 IP 地址信息ip netns exec 84040 ip link set dev veth0_p name eth0
ip netns exec 84040 ip link set dev eth0 up
ip netns exec 84040 ip add add 172.17.0.10/16 dev eth0
ip netns exec 84040 ip route add default via 172.17.0.1进入容器检查网络信息
ip add
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
15: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 7e:36:b3:20:a1:8c brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.10/16 scope global eth0
valid_lft forever preferred_lft forever
ip route show
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.10进入容器测试网络连接
ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=127 time=37.4 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=127 time=37.0 ms
^C
--- 8.8.8.8 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 37.047/37.234/37.422/0.269 ms