docker容器网络

在安装docker时,会自动在host主机上创建三个网络,用docker network ls可以进行查看:

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
b271af4d6598        bridge              bridge              local
95f888208994        host                host                local
5705b1b4107d        none                null                local

none网络

none网络就是什么都没有的网络,挂在none网络下面的容器除了了lo,没有其他任何的网卡,在创建容器的时候可以通过--network=none指定容器使用none网络。

$ docker run -it --network=none busybox
/ # 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

可以看到该容器只有一块网卡lo,封闭意味着隔离,一些对安全性要求高并且不需要联网的应用可以使用 none 网络。

host网络

连接到host网络的容器共享host的网络栈,容器的网络配置跟host的完全相同:

$ docker run -it --network=host busybox
/ # ip l
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
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:0c:29:09:e3:78 brd ff:ff:ff:ff:ff:ff
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue 
    link/ether 02:42:9b:0d:23:8b brd ff:ff:ff:ff:ff:ff
31: vethb6ac730@if30: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0 
    link/ether be:0d:67:bb:5f:9c brd ff:ff:ff:ff:ff:ff
33: veth5819fa7@if32: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0 
    link/ether 8a:a7:7c:de:29:16 brd ff:ff:ff:ff:ff:ff
35: veth7c93491@if34: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0 
    link/ether 9a:19:ce:26:aa:ab brd ff:ff:ff:ff:ff:ff
/ # hostname
ubuntu

容器中能看到host的所有网卡,连hostname也跟host一样。

直接使用 Docker host 的网络最大的好处就是性能,如果容器对网络传输效率有较高要求,则可以选择 host 网络。当然不便之处就是牺牲一些灵活性,比如要考虑端口冲突问题,Docker host 上已经使用的端口就不能再用了。

Docker host 的另一个用途是让容器可以直接配置 host 网路。比如某些跨 host 的网络解决方案,其本身也是以容器方式运行的,这些方案需要对网络进行配置,比如管理 iptables

bridge网络

docker在安装时会创建一个名为docker0的linux bridge。如果容器启动的时候不指定–network,那么容器会默认挂在docker0上。

$ brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.02429b0d238b	no

现在docker0上没有任何网络设备,我们创建一个容器看看。

root@ubuntu:~# docker run -d httpd
3f8da19c11f089cce5b3f85bc016f3403db0ad4af71a7abea0b696afd1886411
root@host1:~# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.02429b0d238b	no		vethe631bd9
root@ubuntu:~# docker exec -it 3f8da19c11f0 bash
root@3f8da19c11f0:/usr/local/apache2# 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
52: eth0@if53: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    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

可以看到一个新的网络设备挂在在docker0上,vethe631bd9就是新创建的httpd容器的虚拟网卡。看了容器内部的网卡为eth0@if53,为什么从外面看到的和容器内部看到的网卡不一样呢?

实际上vethe631bd9eth0@if53是一对veth pair。veth pair是一种成对出现的网络设备,可以理解为一根网线的两端,一端(eth0@if53)在容器内,另一端(vethe631bd9)挂在docker0上,其效果就是相当于(eth0@if53)也挂在docker0上。

还看到eth0@if53已经配置了IP为172.17.0.2,为什么是这个网段,我们通过docker network inspect bridge看一下bridge网络的配置:

$ docker network inspect bridge 
[
    {
        "Name": "bridge",
        "Id": "b271af4d65980ecfa171fdad89636864ec076f45fb8c8558310916bedc7ecda0",
        "Created": "2018-01-22T17:51:21.295766604+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
......

原理bridge网络的Subnet(子网)是172.17.0.0/16,Gateway(网关)是172.17.0.1,这个网关就是docker0。

在容器启动的过程中,docker会自动从172.17.0.0/16中分配一个IP。

自定义容器网络

docker提供了三种user-defined网络驱动:bridge,overlay和macvlan。后两种用于创建跨主机的网络。

可以使用bridge驱动创建类似bridge的网络:

$ docker network create --driver bridge my_net
5e9efda5449ba5a581e9fb91e3afbb1621bacd823b0ad08ef79b5d3cd368e1da
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
b271af4d6598        bridge              bridge              local
95f888208994        host                host                local
5e9efda5449b        my_net              bridge              local
5705b1b4107d        none                null                local
$ brctl show
bridge name	bridge id		STP enabled	interfaces
br-5e9efda5449b		8000.02426b4ed3ee	no		
docker0		8000.02429b0d238b	no		vethe631bd9

这样我们成功穿创建了一个my_net的网络,新增加了一个网桥br-5e9efda5449b,并且5e9efda5449b是my_net网络的短ID。

通过docker network inspect my_net命令查看my_net网络的配置信息:

$ docker network inspect my_net
[
    {
        "Name": "my_net",
        "Id": "5e9efda5449ba5a581e9fb91e3afbb1621bacd823b0ad08ef79b5d3cd368e1da",
        "Created": "2018-01-23T15:44:17.670486371+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
.......

docker自动为my_net网络分配了子网和网关。

同时我们也可以自己指定subnet和gateway,在创建网络的时候加上--subnet--gateway参数就可以了:

$ docker network create --driver bridge --subnet 172.19.0.0/24 --gateway 172.19.0.1 my_net2
1ded797aeede01408e2a70295e7b327a06233ac4e799b7da7e0913db1f41d8dd
$ brctl show 
brctl show 
bridge name	bridge id		STP enabled	interfaces
br-1ded797aeede		8000.0242bfebcd26	no	
$ ifconfig br-1ded797aeede
br-1ded797aeede Link encap:以太网  硬件地址 02:42:bf:eb:cd:26  
          inet 地址:172.19.0.1  广播:172.19.0.255  掩码:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  跃点数:1
          接收数据包:0 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:0 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:0 
          接收字节:0 (0.0 B)  发送字节:0 (0.0 B)
$ docker network inspect my_net2
[
    {
        "Name": "my_net2",
        "Id": "1ded797aeede01408e2a70295e7b327a06233ac4e799b7da7e0913db1f41d8dd",
        "Created": "2018-01-23T15:55:51.894463236+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.19.0.0/24",
                    "Gateway": "172.19.0.1"
                }
......

到这里,我们自己指定了网络。my_net2对应的网桥是br-1ded797aeede

容器要使用新的网络,可以用--network指定:

$ docker run -it --network=my_net2 busybox
/ # 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
56: eth0@if57: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:13:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.19.0.2/24 brd 172.19.0.255 scope global eth0
       valid_lft forever preferred_lft forever

容器分到的地址是172.19.0.2,那么能不能给容器指定一个静态IP呢?通过--ip参数就可以给容器指定静态IP:

$ docker run -it --network=my_net2 --ip 172.19.0.6 busybox
/ # 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
58: eth0@if59: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:13:00:06 brd ff:ff:ff:ff:ff:ff
    inet 172.19.0.6/24 brd 172.19.0.255 scope global eth0
       valid_lft forever preferred_lft forever

到这里,我们给容器指定了静态IP:172.19.0.6

注意:只有通过--subnet创建的网络才能指定静态IP

同主机网络的通信

上面的两个busybox容器都挂在my_net2上,我们测试以下能否互通:

/ # 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
56: eth0@if57: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:13:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.19.0.2/24 brd 172.19.0.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping 172.19.0.6 -c 3
PING 172.19.0.6 (172.19.0.6): 56 data bytes
64 bytes from 172.19.0.6: seq=0 ttl=64 time=0.224 ms
64 bytes from 172.19.0.6: seq=1 ttl=64 time=0.192 ms
64 bytes from 172.19.0.6: seq=2 ttl=64 time=0.336 ms

--- 172.19.0.6 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.192/0.250/0.336 ms

同一网络中的容器、网关之间都是互通的
不同网络中的容器不能互通,通过docker network connect命令可以实现:

$ docker network connect my_net2 3f8da19c11f0
$ docker exec -it 3f8da19c11f0 bash
root@3f8da19c11f0:/usr/local/apache2# ping 172.19.0.6 -c 3
PING 172.19.0.6 (172.19.0.6): 56 data bytes
64 bytes from 172.19.0.6: icmp_seq=0 ttl=64 time=0.162 ms
64 bytes from 172.19.0.6: icmp_seq=1 ttl=64 time=0.196 ms
64 bytes from 172.19.0.6: icmp_seq=2 ttl=64 time=0.160 ms
--- 172.19.0.6 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.160/0.173/0.196/0.000 ms

果然,能够互通了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值