Docker 网络-bridge 模式

容器与主机、容器与容器之间是互相隔离的。同时,我们可以通过配置 docker 网络,为容器创建完全独立的网络命名空间,或者使容器共享主机或者其他容器的网络命名空间,以应对不同场景的需要。

这里有4 种常用的单宿主机网络模式:

  1. bridge 模式;
  2. host 模式;
  3. container 模式;
  4. none 模式。

本节将介绍网络模式中的 bridge 模式。

1. bridge 模式

Docker 服务启动时,会自动在宿主机上创建一个 docker0 虚拟网桥 (Linux Bridge, 可以理解为一个软件虚拟出来的交换机)。它会在挂载到它的网口之间进行转发。同时 Docker 随机分配一个可用的私有 IP 地址给 docker0 接口。如果容器使用默认网络参数启动,那么它的网口也会自动分配一个与 docker0 同网段的 IP 地址。

我们使用命令 ip address show dev docker0 获取 docker0 网络信息,它的地址是 172.17.0.1, 子网掩码为 255.255.0.0,如下图所示:

图片描述

我们来做个测试,看看默认新建的容器是否能互相连通。

使用 busybox 镜像分别运行 b0,b1 两个容器:

docker run -d -t --name b0 busybox
docker run -d -t --name b1 busybox

容器新建并运行成功后,查看两个容器的 IP 地址:

docker inspect --format '{{ .NetworkSettings.IPAddress }}' b0 # 172.17.0.2
docker inspect --format '{{ .NetworkSettings.IPAddress }}' b1 # 172.17.0.3

Tips:获取的 IP 是随机的,跟 Docker 版本与运行环境有关,以自己获取的 IP 为准,下同

两个容器互相 ping 一下,证明它们的网络能连通:

docker exec -it b0 ping 172.17.0.3
docker exec -it b1 ping 172.17.0.2

此时网络拓扑结构如下所示:
图片描述

docker0 拓扑

容器 b1 之后用不到,我们可以先删除它来释放资源。

1.1 自定义网桥

除了使用默认 docker0 做网桥,我们还可以使用 docker network 相关命令自定义网桥:

这里将创建一个网桥 br0,设定网段是 172.71.0.0/24,网关为 172.71.0.1

docker network create -d bridge --subnet '172.71.0.0/24' --gateway '172.71.0.1' br0
# -d 指定管理网络的驱动方式,默认为bridge
# --subnet 指定子网网段
# --gateway 指定默认网关

使用命令 docker network ls 查看当前的 docker 网络列表,发现新增的 br0 网桥。

图片描述

接下来,我们尝试在使用这个网桥 br0 来新建运行两个容器,并测试它们的连通性。使用 busybox 镜像分别运行 b2,b3 两个容器:

docker run -d -t --network br0 --name b2 busybox
docker run -d -t --network br0 --name b3 busybox

容器新建并运行成功后,分别执行下列命令,互相 ping 一下验证网络连通:

docker exec b2 ping b3
docker exec b3 ping b2

图片描述

ping 测试过程中,输入的并不是 IP,而是容器名。在自定义网桥中,容器名会在需要的时候自动解析到对应的 IP,也解决了容器重启可能导致 IP 变动的问题。

其他

不再使用的容器记得删除掉,释放资源和空间

docker rm -f b2 b3
docker network rm br0 # 删除自定义的网桥

1.2 端口映射访问容器

将宿主机的本地端口,与指定容器的服务端口进行映射绑定,之后访问宿主机端口时,会将请求自动转发到容器的端口上,实现外部对容器内网络服务的访问。

创建名为 n0 的 nginx 容器,映射宿主机 8000 端口到它的 80 端口

docker run -d -t -p 8000:80 --name n0 nginx

Tips:指定的宿主机端口必须是未被占用的端口,否则操作会失败,且生成一个无法正常启动的容器 n0, 需要手动删除。

使用 docker port n0 查看 n0 的端口映射信息,显示如下:

80/tcp -> 0.0.0.0:8000

打开浏览器,地址栏输入 http://localhost:8000 或 http:// 宿主机 IP:8000, 都能访问到 n0 的 nginx 服务。

如果需要绑定多个容器端口,可以连续使用 -p 参数多次指定

docker run -d -t -p 8001:80 -p 8433:443 --name n1 ngin

如果不想主动指定宿主机端口,可以使用 -P 参数,宿主机随机使用一个可用端口与容器端口进行映射

docker run -d -t -P --name n2 nginx

如果只想使用宿主机上特定的网口与容器进行映射

docker run -d -t -p 192.168.1.13:8002:80 --name n3 nginx

Tips:此处 192.168.1.13 指代 宿主机映射网口的 IP 地址,需要根据网口的实际 IP 更改 *。

我们执行 docker ps 可能出现如下几个的 nginx 容器:
图片描述
再执行 iptables -t nat -nL 查看下防火墙:

图片描述

比对上面两个的输出,不难发现,这种端口转发方式的本质是通过配置 iptables 规则转发实现的,效率较低,如果容器的服务端口数量过多,需要配置较多的映射,占用大量宿主机端口,也不便于管理。

不再使用的容器记得删除掉,释放资源和空间

docker rm -f n0 n1 n2 n3

2. 小结

使用端口映射访问容器是常用的方式之一,它配置简单,通用性强,可以跨宿主机访问,基本覆盖个人日常使用的场景,但它仍有一些缺陷。