Docker-Advanced(2)-Docker Four Networks&Custom Networks

序文

  • 2つ以上のコンテナはどのように相互に通信しますか?
  • コンテナの再起動後にIPの変更を解決するにはどうすればよいですか?
  • コンテナ名を介してコンテナ間で通信するにはどうすればよいですか?
  • 同じサービスグル​​ープに属するすべてのコンテナが同じネットワークに参加するようにネットワークをカスタマイズするにはどうすればよいですか?

1.ホストネットワーク

  1. Dockerネットワーキングは、ホストとコンテナー間のネットワーク通信を処理するために使用されます
    • コンテナとポートマッピング間の相互接続と通信
    • コンテナのIPが変更されると、影響を受けることなく、サービス名を介してネットワークと直接通信できます。
  2. Dockerが起動していない場合、ホストのネットワーク状態
    • システムはvagrantを介してインストールおよび開始されます
    • この時点で、eth0とlo(ローカル)の2つのネットワークカードがあります。
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.33.10  netmask 255.255.255.0  broadcast 192.168.33.255
        inet6 fe80::a00:27ff:fe29:956c  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:29:95:6c  txqueuelen 1000  (Ethernet)
        RX packets 204  bytes 20733 (20.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 144  bytes 23742 (23.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 64  bytes 5184 (5.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 64  bytes 5184 (5.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
复制代码
  1. Dockerが起動すると、ホストのネットワーク状態
    • この時点で、ホストはdocker0という名前の仮想ブリッジを生成します
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:f7:55:5a:bd  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.33.10  netmask 255.255.255.0  broadcast 192.168.33.255
        inet6 fe80::a00:27ff:fe29:956c  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:29:95:6c  txqueuelen 1000  (Ethernet)
        RX packets 204  bytes 20733 (20.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 144  bytes 23742 (23.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 64  bytes 5184 (5.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 64  bytes 5184 (5.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
复制代码

2.Dockerネットワーク

  1. Dockerネットワークモードコマンドを表示
docker network <COMMAND>
复制代码
  1. 使用できるコマンドは以下のとおりです。
[root@server01 ~]# docker network --help

Usage:  docker network COMMAND

Manage networks

Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks
复制代码
  1. ネットワークカードのリストを表示する
[root@server01 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
ad11a58c25cc   bridge    bridge    local
1524da0505ee   host      host      local
f4cbc4779eaf   none      null      local
复制代码
  1. デフォルトで3つの主要なネットワークモードが作成されていることがわかります
  2. ネットワークカード情報を表示する
[
  {
    "Name": "bridge",
    "Id": "ad11a58c25cc80747576c2ef7c2ca09b960fe0565b4c6ab7032ed9dfdba94ca2",
    "Created": "2022-03-20T12:41:29.966511242Z",
    "Scope": "local",
    "Driver": "bridge",
    "EnableIPv6": false,
    "IPAM": {
      "Driver": "default",
      "Options": null,
      "Config": [
        {
          "Subnet": "172.17.0.0/16",
          "Gateway": "172.17.0.1"
        }
      ]
    },
    "Internal": false,
    "Attachable": false,
    "Ingress": false,
    "ConfigFrom": {
      "Network": ""
    },
    "ConfigOnly": false,
    "Containers": {},
    "Options": {
      "com.docker.network.bridge.default_bridge": "true",
      "com.docker.network.bridge.enable_icc": "true",
      "com.docker.network.bridge.enable_ip_masquerade": "true",
      "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
      # 可以看到bridge用的网桥名称就是docker0
      "com.docker.network.bridge.name": "docker0",
      "com.docker.network.driver.mtu": "1500"
    },
    "Labels": {}
  }
]
复制代码
  1. ネットワークカードの作成と削除
# 原始所有网卡信息
[root@server01 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
ad11a58c25cc   bridge    bridge    local
1524da0505ee   host      host      local
f4cbc4779eaf   none      null      local
# 创建网卡
[root@server01 ~]# docker network create my_network
146a5d4683a8ef8256ce5280eabb719c5d7da061f317f03529dedbf4fe8ee2a5
[root@server01 ~]# docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
ad11a58c25cc   bridge       bridge    local
1524da0505ee   host         host      local
# 默认创建的网卡类型是桥接类型
146a5d4683a8   my_network   bridge    local
f4cbc4779eaf   none         null      local
# 删除网卡
[root@server01 ~]# docker network rm my_network
my_network
[root@server01 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
ad11a58c25cc   bridge    bridge    local
1524da0505ee   host      host      local
f4cbc4779eaf   none      null      local
复制代码

3.ネットワークモード

image.png

3.1ブリッジモード

  1. Dockerサービスはデフォルトでdocker0ブリッジを作成し(docker0内部インターフェースを使用)、ブリッジネットワークの名前はdocker0であり、カーネルレイヤーで他の物理ネットワークカードまたは仮想ネットワークカードを接続し、すべてのコンテナーとローカルホストが同じ物理ネットワーク
  2. Dockerは、デフォルトでdocker0インターフェースのIPアドレスとサブネットマスクを指定します。これにより、ホストとコンテナーはブリッジを介して相互に通信できます。
  3. 各コンテナにipを割り当てて設定し、コンテナをdocker0に接続します。仮想ブリッジは、デフォルトでこのモードになります。
  4. --network bridgeを使用して、コンテナが使用するネットワークモード、デフォルトのブリッジ(docker0)を指定します。
  5. Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为容器ip(Container-IP),同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信
  6. docker run 的时候,如果没有指定network则默认使用的网桥模式就是bridge,使用的就是docker0。在宿主机ifconfig可以看到docker0和创建的的networketh0,eth1,eth2……代表网卡一,网卡二,网卡三……,lo代表127.0.0.1,即localhost,inet addr用来表示网卡的IP地址
  7. 网桥docker0创建一对对等虚拟设备接口一个叫veth,另一个叫eth0,成对匹配
    • 整个宿主机的网桥模式都是docker0,类似一个交换机有一堆接口,每个接口叫veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair
    • 每个容器实例内部同时有一块网卡,每个接口叫eth0
    • docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配。 通过配对网卡,将宿主机上的所有容器都连接到这个内部网络上,两个容器在同一个网络下,会从这个网关下各自拿到分配的ip,此时两个容器的网络互通

image.png

  1. 运行alpine(一个微型的linux版本) 容器,进入redis容器内容查看网络信息和宿主机网络信息
    • docker pull alpine
    • docker run -d --name alpine alpine:latest
    • docker exec -it apline bash
    • alpine容器内部
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
# eth0@if11:表示连接到宿主机的11号网卡信息
10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    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
复制代码
  • 宿主机网络信息
# veth02096c1@if10:表示连接到容器内部的10号网卡
11: veth02096c1@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether fe:e5:f2:56:6d:07 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::fce5:f2ff:fe56:6d07/64 scope link
       valid_lft forever preferred_lft forever
复制代码
  • 对应关系如下

image.png

3.2 host模式

  1. 直接使用宿主机的 IP 地址与外界进行通信,不再需要额外进行NAT 转换
  2. 使用--network host指定
  3. 查看host网卡信息
[
    {
        "Name": "host",
        "Id": "1524da0505eef1c3f188e337551fe0259b99c3e00915fd9eafea288aa4ec69c9",
        "Created": "2022-03-06T06:55:13.717636641Z",
        "Scope": "local",
        # 驱动为host
        "Driver": "host",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": []
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

复制代码
  1. 容器不会获得一个独立的Network Namespace, 而是和宿主机共用一个Network Namespace,不会虚拟出自己的网卡而是使用宿主机的IP和端口

image.png

  1. docker run -d -p ip:ip --network host --name xxx xxxImage
    • 在host模式下无需通过ip来指定端口映射,因为使用的是宿主机的端口和ip
    • docker通过指定--network=host或-net=host启动的容器不能指定端口映射,将会抛出警告
    • 直接执行 docker run -d --network host --name xxx xxxImage 即可

3.3 none模式

  1. 容器有独立的 Network namespace,但并没有对齐进行任何网络设置,如分配veth pair和网卡连接、ip等
  2. 实际中使用较少,因为Docker容器没有网卡、IP、路由等信息,只有一个lo(local表示本地回环),需要我们自己为Docker容器添加网卡、配置IP等
  3. none模式:使用--network none指定
  4. 查看none网卡信息
[
    {
        "Name": "none",
        "Id": "f4cbc4779eafdf5bc4d2fd948ded3e0f8b99c2d2aac425123bda050d58eef0a3",
        "Created": "2022-03-06T06:55:13.712122716Z",
        "Scope": "local",
        # 驱动为空
        "Driver": "null",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": []
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
复制代码
  1. 如果容器启动在此模式下,内部将只有lo地址

3.4 container模式

  1. 新建的容器和已经存在的一个容器共享网络ip和配置,而不会创建自己的网卡,配置自己的IP等
  2. 两个容器除了网络方面,其他的如文件系统、进程列表等依然隔离
  3. 使用--network container:NAME 或者容器ID指定
  4. 先运行基础容器
    • docker run -it --name alpine alpine:latest
[root@server01 ~]# docker run -it --name alpine alpine:latest
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    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
复制代码
  1. 再运行alpine,然后指定基础基础容器
    • docker run -it --network container:alpine --name alpine-01 alpine:latest
[root@server01 ~]# docker run -it --network container:alpine --name alpine-01 alpine:latest
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    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
复制代码
  1. 关闭基础容器,然后再查看alpine-01
    • 此时只有本地回环地址,共享的网络已经没有了
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
复制代码
  1. 所以基于容器模式网络直接依赖性比较强,基础容器网络中断将会导致所有基于此网络的容器全部受到影响

四、网络IP生产规则

  1. docker容器内部的ip是在容器启动时进行分配,所以ip可能会发生改变
    • docker inspect redis | tail -n 20
"Networks": {
    "bridge": {
        "IPAMConfig": null,
        "Links": null,
        "Aliases": null,
        "NetworkID": "ad11a58c25cc80747576c2ef7c2ca09b960fe0565b4c6ab7032ed9dfdba94ca2",
        "EndpointID": "48f16e0663e908688490e3a1fdc688a1b1c28d706ee631facb0c367e343dce76",
        # 默认的网关就是docker0
        "Gateway": "172.17.0.1",
        # 本次分配的ip
        "IPAddress": "172.17.0.2",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "MacAddress": "02:42:ac:11:00:02",
        "DriverOpts": null
    }
}
复制代码
  1. 可以关闭此容器,然后重新运行一个新容器,可以返回ip和上面的可能一样,所以ip会变动

五、自定义网络

  • 之前的links技术已经过时

image.png

  1. 在各自容器内部,通过ip可以ping通,但是通过服务名(--name 指定的名称)缺无法ping通
  2. 自定义桥接网络,自定义网络默认使用的是桥接网络bridge
    • docker network create my_network
  3. 新建容器加入上一步新建的自定义网络
    • docker run -d --network my_network --name alpine01 alpine:latest
    • docker run -d --network my_network --name alpine02 alpine:latest
  4. 原理:自定义网络维护好了主机名和ip的对应关系(ip和域名都能通)
  5. 通过将不同容器加入到同一个网络,就可以实现通过容器名称访问,无论容器如何重启都无需改动依赖服务

おすすめ

転載: juejin.im/post/7103694519203266567
おすすめ