【docker】 Docker 网络

本文介绍 docker 的网络模式

docker 使用 linux 的 Namespaces 技术来进行资源隔离,其中网络使用 Network Namespace 来进行网络隔离。一个 Network Namespace 提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其他的 Network Namespace 隔离。

docker 网络模式

在使用 docker run 创建容器时,可以用 –net 选项指定容器的网络模式,有如下几种模式

  1. host 模式
    –net=host

    容器不使用独立的 Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的

    例如,在 10.10.101.105/24 的机器上用 host 模式启动一个含有 web 应用的 docker 容器,监听 tcp80 端口。在容器中执行任何类似 ifconfig 命令查看网络环境时,看到的都是宿主机上的信息。而外界访问容器中的应用,则直接使用10.10.101.105:80即可,不用任何NAT转换,就如直接跑在宿主机中一样。

  2. container 模式
    –net=${CONTAINER}

    指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。
    新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。
    两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的,两个容器的进程可以通过 lo 网卡设备通信。

  3. none 模式
    –net=none

    在这种模式下,docker 容器拥有自己的 Network Namespace,但是并不为 docker 容器进行任何网络配置。

    这个 docker 容器没有网卡、IP、路由等信息。需要自己为 docker容器添加网卡、配置IP等。

  4. bridge 模式
    –net=bridge

    docker 默认的网络设置,此模式会为每一个容器分配 Network Namespace、设置IP等,并将一个主机上的 docker 容器连接到一个虚拟网桥上

  5. 自定义网络
    –net=user_define_network

    使用用户自定义的网络模式

bridge 模式的拓扑

当 docker 服务启动时,会在宿主上创建一个 docker0 虚拟网桥,在此宿主上启动的容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样宿主上的所有容器就通过交换机连在了一个二层网络中,如下图。

docker bridge 模式拓扑

容器创建时, docker 为会从 RFC1918 所定义的私有 IP 网段中,选择一个和宿主不同的 IP 地址和子网分配给 docker0,连接到 docker0 的容器就从这个子网中选择一个未占用的IP使用。

docker 完成以上网络配置需要才下几步:

  1. 在主机上创建一对虚拟网卡 veth pair 设备(veth 设备总是成对出现,组成了一个数据的通道)
  2. docker 将veth pair设备的一端放在新创建的容器中,并命名为eth0;另一端放在主机中,以 veth65f9 这样类似的名字命名,并将这个网络设备加入到 docker0 网桥中
  3. 从 docker0 子网中分配一个 IP 给容器使用,并设置 docker0 的 IP 地址为容器的默认网关

自定义网络

docker 的 network 子命令可以设置网络相关的配置

1
2
# 列出所有的网络
docker network ls
1
2
# 创建一个网络
docker network create
1
2
# 删除一个网络
docker network rm
1
2
# 把容器接入到指定网络
docker network connect
1
2
# 把容器从网络卸载下来
docker network disconnect
1
2
# 查看网络的详细信息
docker network inspect

各种网络场景(示例)

宿主外部访问容器

一般宿主外部不需要直接访问容器,而是通过 run 命令的 -p 选项将容器的端口映射到宿主的端口。宿主外部通过这个端口访问容器的服务。

容器访问宿主外部

容器可以直接通过宿主的网桥访问宿主外部网络

同一宿主下多个容器组网

使用同一个 bridge 下的容器就是在同一个子网中,容器可以互相联通。但如果不是同一个 bridge 下的容器,默认情况下是不互通的。

创建容器时,可以用 run 命令的 –hostname 选项和 –ip 选项指定容器的 hostname 和 ip
同时可以用 –add-host ${hostname}:${ip} 将条目加入到 /etc/hosts 文件中(只有用户定义的网络可以使用)

跨宿主容器网络

  1. 启动两台 docker 宿主 n1 和 n2,分别安装好 docker-engine 并确保两台宿主之间可以通过 IP 互相访问
  2. 在任务节点上创建网络 multi,例如在 n1 上执行
1
docker network create -d overlay multi

创建成功后,在 n1 和 n2 上都可以用 docker network ls 看到 multi 的网络信息

  1. 在 n1 上创建容器 c1, 在 n2 上创建容器 c2,分别用 –net mulit 指定连接到 multi 网络。通过 ping 可以测试出 c1 可以 ping 通 c2