Docker 网络类型详解
通过 docker network ls
命令来查看本地 docker 服务支持的网络类型。
# 查看 my_httpd 容器信息
docker inspect my_httpd
# 查看 bridge 网络信息
docker inspect bridge
可以看到每起一个容器,在宿主机网络都会新增一个veth-pair
host 网络类型
Docker 使用了 Linux 的 Namespaces 技术来进行资源隔离,如 PID Namespace 隔离进程,Mount Namespace 隔离文件系统,Network Namespace 隔离网络等。一个 Network Namespace 提供了一份独立的网络环境,包括网卡、路由、Iptable 规则等都与其他的 Network Namespace 隔离。
我们可以使用 --net=host 指定 Docker 容器处于 host 类型的网络中。host 模式类似于 Vmware的桥接模式,与宿主机在同一个网络中,但没有独立 IP 地址。一个 Docker 容器一般会分配一个独立的 Network Namespace。但如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。
如下图所示:容器与主机在相同的网络命名空间下面,使用相同的网络协议栈,容器可以直接使用主机的所有网络接口。
# 注:官方的nginx镜像里面不包含ip addr和vim命令,这里是基于官方nginx镜像安装了iproute2
#和vim重新commit了一个guianjun/mynginx:v2.0基础镜像,便于实验
docker run -itd --name my_nginx --net=host -p 80:80 guianjun/mynginx:v2.0 /bin/bash
#在容器中执行ip addr命令,查看网络
docker exec -it my_nginx ip addr
可以看到容器 my_nginx 的网络配置与宿主机 hosts 的网络配置完全一样,在容器中可以看到 host 的所有网卡,并且连 hostname 也是跟宿主机一样的。从网络层面来看,host 模式下的容器只是宿主机上的一个端口,比如这里的 my_nginx 容器映射的是宿主机上的80端口,那么可以根据宿主机 ip+映射端口来实现对容器的访问。
host 模式的特点和应用场景:host 模式简单并且网络传输性能高,host 模式下面的网络模型是最简单和最低延迟的模式,容器进程直接与主机网络接口通信,与物理机性能一致,host 不利于网络自定配置和管理,并且所有主机的容器使用相同的 IP。也不利于主机资源的利用,需要考虑端口冲突问题,缺乏灵活性,如果是对网络性能要求比较高的情况下可以使用该模式,否则应该使用其他模式。
bridge 网络类型(默认类型)
docker 的桥接网络使用虚拟网桥 docker0,bridge 网络用于同一主机上的 docker 容器相互通信,连接到同一个网桥的 docker 容器可以相互通信,当我们启动 docker 时,会自动创建一个默认 bridge 网络,除非我们进行另外的配置,新创建的容器都会自动连接到这个网络,我们也可以自定义自己的 bridge 网络,docker 文档建议使用自定义 bridge 网络,默认的 bridge 网络具有一定的缺陷。连接到同一 bridge 网络的容器可以相互访问彼此任意一个端口,如果不发布端口,外界将无法访问这些容器,在创建容器时,通过 -p 或是 --publish 指令发布端口。
Docker 安装时会自动创建一个命名为 docker0 的 Linux bridge。如果不指定 -network,创建的容器默认都会挂到 docker0 上,容器默认网络模式就是 bridge 模式。
我们安装 Docker 后守护进程将创建一个 linux 虚拟以太网桥 docker0,它会在连接到其上的所有接口之间转发数据包,默认情况下主机上的所有容器都连接到这个内部桥接器,它会将一个接口(虚拟设备对 veth pair)作为容器的 eth0 接口和主机命名空间中的另一个接口。这样容器就获得了私有 IP 地址分配。同时为了防止本地网络上的 ARP 冲突,Docker 守护进程从分配的 IP 地址上生成一个随机 MAC 地址。这样一来容器就和网桥连接起来了,然后通过 iptables NAT 规则和主机上 eth0 网卡交换数据。
ifconfig docker0
docker inspect my_nginx
none 网络类型
none 网络就是无网络配置。挂在这个网络下的容器除了 lo,没有其他任何网卡。容器创建时,可以通过 --net=none 指定使用 none 网络。
主要用于一些对安全性要求高并且不需要联网的应用可以使用 none 网络。比如某个容器的唯一用途是生成随机密码,就可以放到 none 网络中避免密码被窃取。
docker run -itd --net=none --name my_nginx2 guianjun/mynginx:v2.0 /bin/bash
docker exec -it my_nginx2 ip addr