文章目录
当项目大规模使用 Docker 时,容器通信的问题也就产生了。要解决容器通信问题,必须先了解很多关于网络的知识。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker 同样有着很多不完善的地方,网络方面就是 Docker 比较薄弱的部分。因此,有必要深入了解 Docker 的网络知识,以满足更高的网络需求。
Docker网络模式
(一)默认网络
安装 Docker 以后,会默认创建三种网络,可以通过docker network ls
查看
[root@docker ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
9096296381e8 bridge bridge local
374f05e7d063 host host local
c1d28598ab0f none null local
Docker的几种网络模式
网络模式 | 说明 |
---|---|
bridge | 为每一个容器分配、设置 IP 等,并将容器连接到一个 docker0 虚拟网桥,默认为该模式。 |
host | 容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。 |
none | 容器有独立的 Network namespace,但并没有对其进行任何网络设置,如分配 veth pair 和网桥连接,IP 等。 |
container | 新创建的容器不会创建自己的网卡和配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。 |
(二)bridge 网络模式
在该模式中,Docker 守护进程创建了一个虚拟以太网桥docker0
,新建的容器会自动桥接到这个接口,附加在其上的任何网卡之间都能自动转发数据包。
默认情况下,守护进程会创建一对对等虚拟设备接口veth pair
,将其中一个接口设置为容器的eth0
接口(容器的网卡),另一个接口放置在宿主机的命名空间中,以类似vethxxx
这样的名字命名,从而将宿主机上的所有容器都连接到这个内部网络上。
比如运行一个基于 busybox 镜像构建的容器 box01,查看 ip addr:
[root@docker ~]# docker run -it --name box01 busybox:1.31.1
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
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
然后宿主机通过 ip addr 查看信息如下:
[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: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:72:00:c5 brd ff:ff:ff:ff:ff:ff
inet 192.168.126.20/24 brd 192.168.126.255 scope global noprefixroute ens32
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe72:c5/64 scope link
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:1a:ae:04:9e 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:1aff:feae:49e/64 scope link
valid_lft forever preferred_lft forever
5: veth9d47895@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 82:0f:7a:49:af:d9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::800f:7aff:fe49:afd9/64 scope link
valid_lft forever preferred_lft forever
通过以上的比较可以发现,证实了之前所说的:守护进程会创建一对对等虚拟设备接口veth pair
,将其中一个接口设置为容器的 eth0
接口(容器的网卡),另一个接口放置在宿主机的命名空间中,以类似vethxxx
这样的名字命名。
同时,守护进程还会从网桥 docker0 的私有地址空间中分配一个 IP 地址和子网给该容器,并设置 docker0 的 IP 地址为容器的默认网关。也可以安装yum install -y bridge-utils
以后,通过 brctl show 命令查看网桥信息。
[root@docker ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02421aae049e no veth9d47895
[root@docker ~]# ip a
…………
5: veth9d47895@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 82:0f:7a:49:af:d9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::800f:7aff:fe49:afd9/64 scope link
valid_lft forever preferred_lft forever
对于每个容器的 IP 地址和 Gateway 信息,我们可以通过docker inspect 容器名称|ID
进行查看,在 NetworkSettings 节点中可以看到详细信息。
[root@docker ~]# docker inspect -f '{
{.NetworkSettings.IPAddress}}' box01
172.17.0.2
[root@docker ~]# docker inspect -f '{
{.NetworkSettings.Gateway}}' box01
172.17.0.1
[root@docker ~]# docker inspect -f '{
{.NetworkSettings.MacAddress}}' box01
02:42:ac:11:00:02
可以通过docker network inspect bridge
查看所有 bridge 网络模式下的容器,在 Containers 节点中可以看到容器名称。
关于 bridge 网络模式的使用,只需要在创建容器时通过参数--net bridge
或者--network bridge
指定即可,当然这也是创建容器默认使用的网络模式,也就是说这个参数是可以省略的。
Bridge 桥接模式的实现步骤主要如下:
- Docker Daemon 利用 veth pair 技术,在宿主机上创建一对对等虚拟网络接口设备,假设为 veth0 和 veth1。而
veth pair 技术的特性可以保证无论哪一个 veth 接收到网络报文,都会将报文传输给另一方。 - Docker Daemon 将 veth0 附加到 Docker Daemon 创建的 docker0 网桥上。保证宿主机的网络报文可以发往 veth0;
- Docker Daemon 将 veth1 添加到 Docker Container 所属的 namespace 下,并被改名为 eth0。如此一来,宿主机的网络报文若发往 veth0,则立即会被 Container 的 eth0 接收,实现宿主机到 Docker Container 网络的联通性;同时,也保证 Docker Container 单独使用 eth0,实现容器网络环境的隔离性。
(三)host 网络模式
host 网络模式需要在创建容器时通过参数--net host
或者--network host
指定;
采用 host 网络模式的 Docker Container,可以直接使用宿主机的 IP 地址与外界进行通信,若宿主机的eth0
是一个公有 IP,那么容器也拥有这个公有 IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换;
host 网络模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。
基于 host 网络模式创建了一个使用 busybox 镜像构建的容器 box02,查看 ip addr:
[root@docker ~]# docker run -it --name box02 --network host busybox:1.31.1
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:0c:29:72:00:c5 brd ff:ff:ff:ff:ff:ff
inet 192.168.126.20/24 brd 192.168.126.255 scope global ens32
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe72:c5/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue
link/ether 02:42:1a:ae:04:9e 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:1aff:feae:49e/64 scope link
valid_lft forever preferred_lft forever
然后宿主机通过 ip addr 查看信息如下:
[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: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:72:00:c5 brd ff:ff:ff:ff:ff:ff
inet 192.168.126.20/24 brd 192.168.126.255 scope global noprefixroute ens32
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe72:c5/64 scope link
valid_lft forever preferred_lft forever
3: docker