Docker 网络-用户自定义网络-网络命令的使用

基于 Docker18.09.0


本文将和大家分享关于 Docker 用户自定义网络的基本命令的使用,有如下命令:

  • docker network create
  • docker network ls
  • docker network inspect
  • docker network connect
  • docker network disconnect
  • docker network rm

1. 创建网络

除了默认的名为 docker0bridge 网络 , 还可以创建自己的 bridge 网络或 overlay 网络。

  • bridge 网络用于在本机内容器之间的互通

  • overlay 网络用于在不同主机内的容器之间的互通

本文主要针对 bridge 网络进行演示说明, overlay 网络会在以后单独进行讨论。

1.1 创建一个 bridge 网络

运行命令 docker network -d 指定要创建什么类型的网络。
假如不使用 -d 参数,会创建 bridge 网络

$ docker network create -d bridge   my-net
# 或者
$ docker network create  my-net

查看网络源数据

$ docker network inspect my-net
[
    {
        "Name": "my-net",
        "Id": "67b19436a9e361c8b9da4034c5903c4903444cecd3ecdbde62bbaf70828d49d9",
        "Created": "2018-12-10T07:22:53.2694852Z",
        "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": {},
        "Options": {},
        "Labels": {}
    }
]

Doker 会为自定义的网络自动分配一个子网("Subnet": "172.18.0.0/16")。

1.2 创建一个 bridge 网络并指定子网

创建一个网络并指定子网为 172.20.0.0/16

$ docker network create  --subnet=172.20.0.0/16 my-net_172_20
$ docker network inspect  my-net_172_20
[
    {
        "Name": "my-net_172_20",
        "Scope": "local",
        ...略...
            "Config": [
                {
                    "Subnet": "172.20.0.0/16"
                }
            ]
        },
        ...略...
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

1.3 创建一个网络使用 --label 添加元数据

在创建一个网络的时候使用 --label 为此网络指定一些元数据信息。
比如下面示例是创建 my-net_label ,并指定网络名称为 my-net_label,项目名为 LB_nginx

$ docker network create \
> --label network_name=my-net_label \
> --label project=LB_nginx \
> my-net_label
83744cec9eef04ae0ba59709041194f4ec7e10714a212086d11df6518295273c

查看元数据,部分数据已截断

$ docker network inspect --format='' my-net_label
        "Labels": {
            "network_name": "my-net_label",
            "project": "LB_nginx"
        }

更多的选项和参数请执行命令 docker network create --help


2. 把容器连接到网络

您可以将现有容器连接到一个或多个网络。
容器可以连接到使用不同网络驱动程序的网络,比如连接到 bridge 网络或者 overlay 网络。
连接后,容器可以使用其他容器的IP地址或名称进行通信。

2.1 简单容器网络的连接示例

Docker 网络-用户自定义网络-网络命令的使用_第1张图片
简单网络

说明:

  1. 上图中表明的意思是,在一台 Docker 主机 Dokcer Host 上有三个容器 。
  2. 三个容器分别连接到两个不同的网络中。
  • 容器 container1 连接到默认的桥接网络 bridge
  • 容器 container2 连接到默认的网络的 bridge,同时它还连接到自定义的桥接网络 my-net 中。
  • 容器 container3 也连接到自定义的桥接网络 my-net

接下来我们就来实际操作一下,并观察各个容器网络的配置情况以及两个网桥的情况。

1.首先,创建并运行两个容器,container1container2

$ docker run -itd --rm --name=container1 busybox
368a503800d4007627d0b63946ef495ae8d5cc225fb7dd265fac62e40268b5f2

# shark @ SharkAir in ~/docker_files/mysql-docker/5.7 on git:mysql-server x [20:59:43]
$ docker run -itd --rm --name=container2 busybox
8a83b0d89c2005f488d00e5dc4d46812a2aeb7f1bcec9f061d9762f6c901275e

2.2 创建一个隔离的桥接网络 my-net

下面在创建网络的时候,使用了 --subnet 为此网络指定了一个子网 172.20.0.0/16

# shark @ SharkAir in ~/docker_files/mysql-docker/5.7 on git:mysql-server x [21:01:47] C:1
$ docker network create  -d bridge --subnet 172.20.0.0/16 my-net
124cb50f08a8ec2a0af44365505e16b3f77b5671373639a1e23f8535a9054d0a

注意现在 container1container2 都被自动连接在默认的桥接网络 bridge

# 部分内容
"Containers": {
            "368a503800d4007627d0b63946ef495ae8d5cc225fb7dd265fac62e40268b5f2": {
                "Name": "container1",
                "EndpointID": "d02b2ab691e5940a74de77ec6a68d35d52c8800014a96f830f04890971587ce2",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "8a83b0d89c2005f488d00e5dc4d46812a2aeb7f1bcec9f061d9762f6c901275e": {
                "Name": "container2",
                "EndpointID": "2e330964b4cc2b5897eeb9fac15dbc03e4326cc47c087e0276de88509f64a0ac",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            }
        },

2.3 现在将 container2 加入到my-net` 网络中

$ docker network connect my-net container2

查看 my-net 网络,以验证

# shark @ SharkAir in ~/docker_files/mysql-docker/5.7 on git:mysql-server x [21:07:16]
$ docker network inspect my-net
[
    {
        "Name": "my-net",
        "Id": "124cb50f08a8ec2a0af44365505e16b3f77b5671373639a1e23f8535a9054d0a",
        "Created": "2018-12-11T13:02:03.0854486Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.20.0.0/16"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "8a83b0d89c2005f488d00e5dc4d46812a2aeb7f1bcec9f061d9762f6c901275e": {
                "Name": "container2",
                "EndpointID": "2663b56686a331e68de1a0c5955d9f3b8ef102653547e43f5d9ef8891d84ffd2",
                "MacAddress": "02:42:ac:14:00:02",
                "IPv4Address": "172.20.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

2.4 运行第三个容器并指定网络。

下面我们运行第三个容器 container3,并且同时使用 --network 指定其加入网络 my-net, 还使用了 --ip 来指定分配给容器的具体 IP 地址。

$ docker run -itd --rm --name=container3 --network=my-net --ip=172.20.0.100 busybox
db4ef2529e81e20508e029ade69ffae08df6dcc538d426b49ca1d9b830d7f0c7

注意:
只要为容器指定的IP地址是网络子网中的一部分,连接到网络时就可以使用 --ip--ip6 标记将IPv4或IPv6地址分配给容器。
在使用用户定义的网络时以这种方式指定IP地址时,配置将作为容器配置的一部分保留,并在重新加载容器时应用。
使用非用户定义的网络时,不会保留分配的IP地址,无法保证在Docker守护程序重新启动时容器的子网不会更改。

2.5 查看容器三的源数据网络部分

部分内容已截断

$ docker inspect container3
"Networks": {
                "my-net": {
                    "IPAMConfig": {
                        "IPv4Address": "172.20.0.100"   # 指定分配的地址
                    },
                    "Links": null,
                    "Aliases": [
                        "db4ef2529e81"
                    ],
                    "NetworkID": "124cb50f08a8ec2a0af44365505e16b3f77b5671373639a1e23f8535a9054d0a",
                    "EndpointID": "ec7774f1936d056ff4b39a862972e11c102d53c61669e5c230e47be35d65ca08",
                    "Gateway": "172.20.0.1",
                    "IPAddress": "172.20.0.100",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:14:00:64",
                    "DriverOpts": null
                }
            }

2.6 再来查看容器二的元数据网络部分

            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "8a5f470ffe774f4f96a712642ed361fbeb0d8e66018e1d629ab44cfdf3e42a05",
                    "EndpointID": "2e330964b4cc2b5897eeb9fac15dbc03e4326cc47c087e0276de88509f64a0ac",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.3",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:03",
                    "DriverOpts": null
                },
                "my-net": {
                    "IPAMConfig": {},
                    "Links": null,
                    "Aliases": [
                        "8a83b0d89c20"
                    ],
                    "NetworkID": "124cb50f08a8ec2a0af44365505e16b3f77b5671373639a1e23f8535a9054d0a",
                    "EndpointID": "2663b56686a331e68de1a0c5955d9f3b8ef102653547e43f5d9ef8891d84ffd2",
                    "Gateway": "172.20.0.1",
                    "IPAddress": "172.20.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:14:00:02",
                    "DriverOpts": null
                }
            }

可以发现 container2 同时加入了两个网络 bridgemy-net ,并且有两个地址 172.17.0.3172.20.0.2

2.7 进入容器 container2 中,查看网卡信息

# shark @ SharkAir in ~ [21:40:45]
$ docker exec -it container2 /bin/sh
/ # ip  -4 a
1: lo:  mtu 65536 qdisc noqueue qlen 1
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
97: eth0@if98:  mtu 1500 qdisc noqueue
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
100: eth1@if101:  mtu 1500 qdisc noqueue
    inet 172.20.0.2/16 brd 172.20.255.255 scope global eth1
       valid_lft forever preferred_lft forever

container2 有两个网络接口卡,分别分配了 IP地址。
这是因为,我们一开始运行这个容器的时候,被连接到默认的网络上,后来我们又执行了 docker network connect 命令,把它连接到了 my-net 网络上了,所以这使其有两个网络,并且有两个网卡。

2.8 尝试利用容器名进行通信测试

Docker嵌入式DNS服务器可以为连接到给定网络的容器启用名称解析。

也就是说目前在 container2 中可以使用容器名和 container3 进行通信。
但是由于默认的网络 bridge 只支持通过 IP 地址通信,所以当 container2container3 互相通信时,只能通过彼此的 IP 地址了。

# shark @ SharkAir in ~ [22:19:51]
$ docker exec -it container2 /bin/sh
/ # ping -w 2 container3
PING container3 (172.20.0.100): 56 data bytes
64 bytes from 172.20.0.100: seq=0 ttl=64 time=0.406 ms
64 bytes from 172.20.0.100: seq=1 ttl=64 time=0.176 ms

--- container3 ping statistics ---
3 packets transmitted, 2 packets received, 33% packet loss
round-trip min/avg/max = 0.176/0.291/0.406 ms
/ # ping -w 2 container1
ping: bad address 'container1'
/ # ping -w 2 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.246 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.162 ms

--- 172.17.0.2 ping statistics ---
3 packets transmitted, 2 packets received, 33% packet loss
round-trip min/avg/max = 0.162/0.204/0.246 ms
/ # exit       # 退出容器

# shark @ SharkAir in ~ [22:25:11]
$

注意:
container3container1 并没有任何共同的网络,所以他们是无法通信的。

# shark @ SharkAir in ~ [22:29:52]
$ docker exec -it container3 /bin/sh
/ # ping -w 2 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes

--- 172.17.0.2 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss
/ #

其实即使容器未运行,您也可以将容器连接到网络。但是,docker network inspect仅显示有关正在运行的容器的信息。

3. 使用容器别名

容器的别名只能在自定义网络中有效。
容器的别名只在其针对的网络中有效。

3.1 一个容器可以在不同的网络中分别使用不同的容器别名

a. 创建另一个名为local_alias 的桥接网络

$ docker network create local_alias
ade171853dd89d36411bff45f2b1356fc622fa1e74e6d6df338df4f129b58aac

b. 运行一个新的容器 container4 , 并加入到网络 local_alias, 同时使用 --network-alias 指定这个容器在此网络中的别名为 auto_git

$ docker run -itd --rm --name=container4 --network=local_alias --network-alias=auto_git  busybox
fab547bb39669c3b9d9f8d4816fe9c637a0b1835516296a6d645229a51fb423e

c. 把容器 container4 加入到网络 my-net, 同时使用 --alias 指定容器在这个网络中的别名为 auto_ansible

$ docker network connect --alias auto_ansible my-net container4

d. 分别进入容器 container3container4 中进行连通性测试。

container3

Docker 网络-用户自定义网络-网络命令的使用_第2张图片
image.png

可以看到同一个容器有多个别名时,每个别名只能在当时绑定到那个网络中有效。

Docker 网络-用户自定义网络-网络命令的使用_第3张图片
container4
Docker 网络-用户自定义网络-网络命令的使用_第4张图片
image.png

从上图中也不难发现,同一个容器有多个别名时,每个别名会被解析为其对应网络中的地址。

3.2 多个容器在相同的网络中可以使用一个别名

a. 运行容器 container5container6 且加入到网络 my-net , 并且使用 --network-alias 指定一样的容器别名为 multiapps

$ docker run -itd --rm --name=container5 --network='my-net' --network-alias=multiapps  busybox
f25abbc871c9c513fc20bdbc0b8e620e3ed0a658ec84fea44d5bddc832d8034f

$ docker run -itd --rm --name=container6 --network='my-net' --network-alias=multiapps  busybox
bd7372233e9092ddb758db65724b496ba2e48724a339cd8ed11fe261b786499e

b. 查看 my-net 网络的元数据

以下是部分内容

 "bd7372233e9092ddb758db65724b496ba2e48724a339cd8ed11fe261b786499e": {
                "Name": "container6",
                "EndpointID": "ec9483fce8f580bdd3d2ea05c17ea3cd7245a8a5c0c51c66074ca50a6f3d2254",
                "MacAddress": "02:42:ac:14:00:05",
                "IPv4Address": "172.20.0.5/16",
                "IPv6Address": ""
            },
            "db4ef2529e81e20508e029ade69ffae08df6dcc538d426b49ca1d9b830d7f0c7": {
                "Name": "container3",
                "EndpointID": "ec7774f1936d056ff4b39a862972e11c102d53c61669e5c230e47be35d65ca08",
                "MacAddress": "02:42:ac:14:00:64",
                "IPv4Address": "172.20.0.100/16",
                "IPv6Address": ""
            },
            "f25abbc871c9c513fc20bdbc0b8e620e3ed0a658ec84fea44d5bddc832d8034f": {
                "Name": "container5",
                "EndpointID": "9e0d28500b688d30443be25ef253cdba684f46221f57dcfe590b2eb44aa7cf74",
                "MacAddress": "02:42:ac:14:00:04",
                "IPv4Address": "172.20.0.4/16",
                "IPv6Address": ""
            },

可以看到当前网络中
container5 的地址是 172.20.0.4/16
container6 的地址是 172.20.0.5/16

c. 进入到容器 container3 中持续 ping 容器的别名 multiapps

$ docker exec -it container3 /bin/sh
/ # ping multiapps
PING multiapps (172.20.0.5): 56 data bytes
64 bytes from 172.20.0.5: seq=0 ttl=64 time=0.186 ms
64 bytes from 172.20.0.5: seq=1 ttl=64 time=0.176 ms
64 bytes from 172.20.0.5: seq=2 ttl=64 time=0.175 ms

d. 打开另一终端,断开容器 container6 到网络 my-net 的连接。

$ docker network disconnect my-net container6

e. 再次会到原来在 container3 中持续 ping 的终端中

发现应无法 ping 通原来解析的地址的,因为下 container6 已经从 my-net 网络中断开了。

但是我们仍然可以再次使用 multiapps 这个别名和另外的容器 (cotainer5) 继续通信。

Ctrl + c 组合结束当前的 ping, 重新 ping multiapps

Docker 网络-用户自定义网络-网络命令的使用_第5张图片
image.png

可以发现 multiapps 被解析为容器 container5 的 IP 地址 172.20.0.4

4. 从网络中断开一个容器的连接

docker  network  disconnect     网络名     容器名

5. 删除一个自定义的网络

docker  network  rm    网络名

你可能感兴趣的:(Docker 网络-用户自定义网络-网络命令的使用)