Docker 网络模式

  • bridge
  • host
  • container模式
  • none
  • 用户自定义模式(bridge、overlay、macvlan)

Docker的网络模式大概可以分为5种类型。安装完 Docker,宿主机默认会创建三个网络,分别是bridge网络,host网络,none网络,可以使用docker network ls命令查看。

[root@tuling ~]$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
99fe18249fa6        bridge              bridge              local
e60bf8b6ed5b        host                host                local
3a142d398cf9        none                null                local

bridge方式(默认)

容器的默认网络模式,docker在安装时会创建一个名为docker0的Linux bridge,在不指定--network的情况下,创建的容器都会默认挂到docker0上面。bridge模式为容器创建独立的网络栈,保证容器内的进程使用独立的网络环境,使容器之间,容器和docker host之间实现网络隔离。

Host IP为192.168.0.2, 容器网络为172.17.0.0/16 下边我们看下docker所提供的四种网络: 创建容器:(由于是默认设置,这里没指定网络--net="bridge"。另外可以看到容器内创建了eth0)

[root@localhost ~]$ docker run -i -t centos:centos7 /bin/bash
root@e2187aa35875:$ ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN
    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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
75: eth0:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link
       valid_lft forever preferred_lft forever

容器与Host网络是连通的:

root@e2187aa35875:# ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2): 48 data bytes
56 bytes from 192.168.0.2: icmp_seq=0 ttl=64 time=0.124 ms
# eth0实际上是veth pair的一端,另一端(vethb689485)连在docker0网桥上:
[root@localhost ~]$ ethtool -S vethb689485
NIC statistics:
     peer_ifindex: 75
[root@localhost ~]$ brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.56847afe9799       no              vethb689485

原理

通过Iptables实现容器内访问外部网络:

[root@localhost ~]# iptables-save |grep 172.17.0.*
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A FORWARD -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 5000 -j ACCEPT

none方式

指定方法: --net="none" 可以看到,这样创建出来的容器完全没有网络:

[root@localhost ~]$ docker run -i -t --net="none"  centos:centos7 /bin/bash
root@061364719a22:$ ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN
    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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
root@061364719a22:$ ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2): 48 data bytes
ping: sending packet: Network is unreachable

那这种方式,有什么用途呢? 这种方式将网络创建的责任完全交给用户。 可以实现更加灵活复杂的网络。 另外这种容器可以可以通过link容器实现通信。

host方式

指定方法:--net="host" 使用host模式的容器可以直接使用docker host的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。

container复用方式

指定方法: --net="container:name or id" 如下例子可以看出来,两者的网络完全相同。

[root@localhost ~]$ docker run -i -t   centos:centos7 /bin/bash
root@02aac28b9234:$ ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN
    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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
77: eth0:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:3/64 scope link
       valid_lft forever preferred_lft forever
[root@localhost ~]$ docker run -i -t --net="container:02aac28b9234"  centos:centos7 /bin/bash
root@02aac28b9234:$ ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN
    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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
77: eth0:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:3/64 scope link
       valid_lft forever preferred_lft forever

这样的好处是如果部署一个应用,可以将应用的不同组件部署在不同的容器中,对外可以看上出是一个整体

user-defined模式

用户自定义模式主要可选的有三种网络驱动:bridge、overlay、macvlan。bridge驱动用于创建类似于前面提到的bridge网络;overlay和macvlan驱动用于创建跨主机的网络、IP等。

跨主机网络会在后面高级课程讲到。

可以在启动容器之前在Docker中创建网络。这可以使用以下命令完成 语法:

docker network create --driver drivername name

选项:

  • drivername - 这是用于网络驱动程序的名称。
  • name - 这是给网络的名称。

这边用bridge举例:

[root@tuling ~]$ docker network create --driver bridge new_nw
c88bc38133ea9c8a9657d915294b4aa42525240096f40e607b4819ff5e1539ee

查看:

[root@tuling ~]$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
99fe18249fa6        bridge              bridge              local
e60bf8b6ed5b        host                host                local
c88bc38133ea        new_nw              bridge              local
3a142d398cf9        none                null                local

现在可以在启动容器时附加新网络。所以让我们使用以下命令启动ubuntu容器

sudo docker run -dit --network=new_nw ubuntu:latest /bin/bash

现在,如果我们通过以下命令检查网络名称,您现在将看到容器已连接到新的网桥。

[root@tuling ~]$ docker network inspect new_nw
[
    {
        "Name": "new_nw",
        "Id": "c88bc38133ea9c8a9657d915294b4aa42525240096f40e607b4819ff5e1539ee",
        "Created": "2020-02-27T11:25:09.921639153+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "93d3c6b0ab95e145346bb6ab47e3e85af5b6c01efce3036527e1681f568959a7": {
                "Name": "stupefied_pare",
                "EndpointID": "888a4cdcf0448e7216ee5ee4c5ded4a4c04e395f6f62fb112639a1ae61f9b0ec",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

发现一个容器已经链接到网桥。

results matching ""

    No results matching ""