Docker Network 简介

2018-03-12 container linux

简介

在启动时可以通过 --network 参数指定。

None

在容器中不会创建任何的外部路由,不过仍然会存在一个回环地址。

# docker run -it --name foobar --network none alpine sh

此时只有一个 lo 设备。

Host

与主机共享所有的网络设备,不会虚拟自己的网络设备。

# docker run -it --name foobar --network host alpine sh

当通过 ifconfig 查看网络设备信息时,会发现,根主机上的信息完全一样。

实际上,Docker 通过内核提供的 Network Namespace 隔离网卡、路由、iptable 等,而所谓的 Host 模式,就是没有新建网络的命名空间。

Container

指定一个容器的名称或者 ID ,会与某个容器共享网络,包括 IP、端口范围等。

# docker run -it --name foobar alpine sh
# docker run -it --name test --net=container:foobar alpine sh

可以看到,后来启动的 test 容器与 foobar 容器的网络配置是一样的。

与上述的 Host 模式有些类似,此时,两个不同的容器之间共享 Network Namespace 空间。

Bridge

这也是默认的,通过 veth 接口连接到虚拟 Bridge 上,此时,在主机以及容器侧会分别存在一个 veth 设备,通过网桥以及 iptables nat 表进行通讯。

Bridge 模式

在 Docker Server 启动时,默认会在主机上创建一个名为 docker0 的虚拟网桥,该主机上所有启动的 Docker 容器会连接到这个虚拟网桥上,其工作方式类似于物理交换机,主机上的所有容器就通过交换机连在了一个二层网络中。

接着要为容器分配 IP 了,默认会从私有 IP 网段中,选择一个和宿主机不同的 IP 地址和子网分配给 docker0 ,所有连接到 docker0 的容器就从这个子网中分配一个未占用的 IP 。

docker bridge

如上容器中,使用的是 172.17.0.0/16 这个网段,并将 172.17.0.1 分配给 docker0 网桥。

示例

如下,启动两个容器,然后观察内部的网络配置。

----- 创建两个容器
# docker run -itd --name foo alpine sh
# docker run -itd --name bar alpine sh

----- 连接到容器,并查看网络配置
# docker exec -it foo sh
/ # ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:03
          inet addr:172.17.0.3  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:32 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:4306 (4.2 KiB)  TX bytes:0 (0.0 B)
# docker exec -it bar sh
/ # ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:04  
          inet addr:172.17.0.4  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:32 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:4306 (4.2 KiB)  TX bytes:0 (0.0 B)

----- 在主机上查看Bridge信息
# ifconfig docker0
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:42ff:fe88:75c5  prefixlen 64  scopeid 0x20<link>
        ether 02:42:42:88:75:c5  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 68  bytes 9984 (9.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
# ip link show docker0
7: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 02:42:42:88:75:c5 brd ff:ff:ff:ff:ff:ff

----- 查看网络
# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
ff951e99dbc2        bridge              bridge              local
a4b2bea17aff        host                host                local
94484d413a30        none                null                local

自定义模式

与默认的 bridge 原理一样,但自定义网络具备内部 DNS 发现,可以通过容器名或者主机名容器之间网络通信。

----- 创建一个test网络
# docker network create test

----- 查看当前网络
# docker network ls

----- 启动容器
# docker run -it --name foo --net=test alpine
/ # ping bar -c 3
PING bar (172.19.0.3): 56 data bytes
64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.110 ms
64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.082 ms
64 bytes from 172.19.0.3: seq=2 ttl=64 time=0.180 ms

--- bar ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.082/0.124/0.180 ms

# docker run -it --name bar --net=test alpine
/ # ping foo -c 3
PING foo (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.115 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.102 ms
64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.069 ms

--- foo ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.069/0.095/0.115 ms

可以看到,直接通过容器名可以 ping 通,实际上是在 /etc/hosts 中添加了一条记录。