当前位置: 首页 > article >正文

Docker 网络基本概念

在之前讲 Redis 集群搭建的时候,我们用过一个选项 --net host​,现在就来讲讲该选项,以及 Docker 的网络。

docker run -d --name redis-node-1 --net host --privileged=true -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381

网络情况

我们先停止 Docker:systemctl stop docker

在不启动 Docker 的情况下,网络情况是这样的:

$ ifconfig
enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.2.242  netmask 255.255.255.0  broadcast 192.168.2.255
        inet6 fe80::3c89:876e:2930:5286  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:74:1d:cd  txqueuelen 1000  (Ethernet)
        RX packets 90493  bytes 13330101 (12.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 38633  bytes 3330369 (3.1 MiB)
        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 6230364  bytes 7704637318 (7.1 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 6230364  bytes 7704637318 (7.1 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

virbr0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.122.1  netmask 255.255.255.0  broadcast 192.168.122.255
        ether 52:54:00:06:12:45  txqueuelen 1000  (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

第一个 enp0s8,有一个 ip 地址 192.168.2.242,就是我们宿主机的地址

第二个 lo,就是 localhost 的简写,指本地回环链路;

第三个:virbr0,用的较少,了解即可。在虚拟机里,安装一个 Centos 的过程中,如果有选择相关虚拟化的的服务安装系统后,启动网卡时会发现有一个以网桥连接的私网地址的 virbr0 网卡(virbr0 网卡还有一个固定的默认 IP 地址 192.168.122.1),是做虚拟机网桥的使用的,其作用是为连接其上的虚机网卡提供 NAT 访问外网的功能。

之前学习 Linux 安装,勾选安装系统的时候附带了 libvirt 服务才会生成的一个东西,如果不需要可以直接将 libvirtd 服务卸载:yum remove libvirt-libs.x86_64

docker 启动后,多了一个 docker0 的虚拟网桥:

$ ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:c0ff:fe81:167e  prefixlen 64  scopeid 0x20<link>
        ether 02:42:c0:81:16:7e  txqueuelen 0  (Ethernet)
        RX packets 57719  bytes 2948857 (2.8 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 60032  bytes 75842649 (72.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

容器与容器之间、容器和宿主机之间,就是通过该虚拟网桥来通信的。

查看 docker 网络模式,这是安装 Docker 后,默认创建的:

$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
5bd056a8204a   bridge    bridge    local
553d2c47bcaa   host      host      local
1ddfe19eb462   none      null      local

我们主要掌握前 2 个,第 3 个 none 很少用到。

我们看看文档:

$ 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

Run 'docker network COMMAND --help' for more information on a command.

可以创建一个网络:

$ docker network create aa_network
9eeb4fd0bf15a59d77bdba7e40594eb30ddd2c2c2ad66df706608a939cd2d193


$ docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
9eeb4fd0bf15   aa_network   bridge    local
5bd056a8204a   bridge       bridge    local
553d2c47bcaa   host         host      local
1ddfe19eb462   none         null      local

NAME 为 bridge 的网络,是桥接模式;NAME 为 host 的是主机模式

查看网络源数据:docker network inspect XXX网络名字

$ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "5bd056a8204a81086acd846de2d0791373671f14a5f6880ebcbf7f4ddceb92cb",
        "Created": "2023-09-10T12:10:26.138357898+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"
                }
            ]
        },
        "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",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

Docker 的网络能解决什么问题:

  • 容器间的互联和通信以及端口映射
  • 容器 IP 变动时,可以通过服务名直接网络通信而不受到影响

访问一个容器,比较关键的一点是在不在同一网段。目前我们是在单机运行 Docker,所以这个问题不明显;

在工作中,则设计到多个 Docker,他们之间的网络管理和容器调用的规划,就得用到 Docker 网络的问题了

网络模式

网络模式简介
bridge为每一个容器分配、设置 IP 等,并将容器连接到一个 docker0。虚拟网桥,默认是该模式
host容器将不会虚拟出自己的网课,配置自己的 IP 等,而是使用宿主机的 IP 和端口
none容器有独立的 Network namespace,但并没有对其进行任何网络设置,
如分配 veth pair 和网桥连接,IP 等
container新创建的容器不会创建自己的网卡和配置自己的 IP,
而是和一个指定的容器共享 IP、端口范围等

  • bridge 模式:使用–network bridge 指定,默认使用 docker0。默认模式,最常见的模式
  • host 模式:使用–network host 指定
  • none 模式:使用–network none 指定,几乎不用
  • container 模式:使用–network container:NAME 或者容器 ID 指定

接下来我们通过一个实例,来理解为什么我们要学习这个 Docker 的网络知识

容器实例内默认网络 IP 生产规则

先启动两个 ubuntu 容器实例:

$ docker run -it --name u1 ubuntu 

$ docker run -it --name u2 ubuntu 

$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
3e1c46b6b32e   ubuntu    "bash"    8 seconds ago    Up 7 seconds              u2
64fecffbfaca   ubuntu    "bash"    26 seconds ago   Up 25 seconds             u1

接下来查看下容器内的信息:docker inspect u1​,最后面有网络的信息:

"Networks": {
    "bridge": {
        "IPAMConfig": null,
        "Links": null,
        "Aliases": null,
        "NetworkID": "5bd056a8204a81086acd846de2d0791373671f14a5f6880ebcbf7f4ddceb92cb",
        "EndpointID": "9b0b1229700e53ea0651dd347d599d3873fa6f00ad92e255c72c2c17fabc87e8",
        "Gateway": "172.17.0.1",
        "IPAddress": "172.17.0.2",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "MacAddress": "02:42:ac:11:00:02",
        "DriverOpts": null
    }
}

可以看到目前是桥接模式,网关是 172.17.0.1,容器本身的 IP 是 172.17.0.2

u2 的信息:

"Networks": {
    "bridge": {
        "IPAMConfig": null,
        "Links": null,
        "Aliases": null,
        "NetworkID": "5bd056a8204a81086acd846de2d0791373671f14a5f6880ebcbf7f4ddceb92cb",
        "EndpointID": "3acf96d0214c8bb088e615e5e0544f19527e7da4fe8dd2cf57dee9f4f72c8ef0",
        "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
    }
}

如果我们删除 u2 实例,再启动一个新的 u3,并查看其休息:

$ docker rm -f u2


$ docker run -it --name u3 ubuntu 


$ docker inspect u3
 "Networks": {
    "bridge": {
        "IPAMConfig": null,
        "Links": null,
        "Aliases": null,
        "NetworkID": "5bd056a8204a81086acd846de2d0791373671f14a5f6880ebcbf7f4ddceb92cb",
        "EndpointID": "371217a338a6787dd444ebd315fe5fee14b6346d2dd90601bcc49a29b7ecdfda",
        "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
    }
}

可以看到 u3 的 IP,和之前 u2 的一样。如果我们想要 u2 的服务,结果 u2 被删除了,请求发到 u3 了,那么可能就会出错。

结论:docker 容器内部的 ip 是有可能会发生改变的。

为此,有必要自己做一些网络设计,例如创建一个新的网络模式,让部分容器在该网络模式下运行。

bridge

Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),该桥接网络的名称为 docker0,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信。示意图:

说明:

  • Docker 使用 Linux 桥接,在宿主机虚拟一个 Docker 容器网桥(docker0),Docker 启动一个容器时会根据 Docker 网桥的网段分配给容器一个 IP 地址,称为 Container-IP,同时 Docker 网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的 Container-IP 直接通信。
  • docker run 的时候,没有指定 network 的话默认使用的网桥模式就是 bridge,使用的就是 docker0。在宿主机 ifconfig,就可以看到 docker0 和自己 create 的 network(后面讲)eth0,eth1,eth2……代表网卡一,网卡二,网卡三……,lo 代表 127.0.0.1,即 localhost,inet addr 用来表示网卡的 IP 地址
  • 网桥 docker0 创建一对对等虚拟设备接口一个叫 veth,另一个叫 eth0,成对匹配。
    • 整个宿主机的网桥模式都是 docker0,类似一个交换机有一堆接口,每个接口叫 veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫 veth pair);
    • 每个容器实例内部也有一块网卡,每个接口叫 eth0;
    • docker0 上面的每个 veth 匹配某个容器实例内部的 eth0,两两配对,一一匹配。

通过上述,将宿主机上的所有容器都连接到这个内部网络上,两个容器在同一个网络下,会从这个网关下各自拿到分配的 ip,此时两个容器的网络是互通的。

接下来我们两两匹配验证,启动两个 Tomcat:

docker run -d -p 8081:8080 --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --name tomcat82 billygoo/tomcat8-jdk8

然后我们可以用 ip addr 命令查看,在下方多了两个 veth 的:

61: veth6ddaa35@if60: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether e6:d2:ee:03:d7:7e brd ff:ff:ff:ff:ff:ff link-netnsid 2
    inet6 fe80::e4d2:eeff:fe03:d77e/64 scope link 
       valid_lft forever preferred_lft forever


63: veth6b10f89@if62: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether fa:f7:44:71:39:65 brd ff:ff:ff:ff:ff:ff link-netnsid 3
    inet6 fe80::f8f7:44ff:fe71:3965/64 scope link 
       valid_lft forever preferred_lft forever

进入到容器内部,可以看到有 eth0 的:

$ docker exec -it tomcat81 bash


$ ip addr
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

60: eth0@if61: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

可以看到 eho0 和 veth 是一一配对的,

接下来介绍下 host 模式。

host

host,主机模式,直接使用宿主机的 IP 地址与外界进行通信,不再需要额外进行 NAT 转换。

容器将不会获得一个独立的 Network Namespace, 而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡而是使用宿主机的 IP 和端口。示意图:

再启动一个 Tomcat:可以看到有一个警告,不太推荐该种模式

$ docker run -d -p 8083:8080 --network host --name tomcat83 billygoo/tomcat8-jdk8
WARNING: Published ports are discarded when using host network mode
09a334d59bc97365d886911be278ebcd9e4dff637dcda97a6687fe3e9b1d2335

为什么有警告?docker 启动时指定–network=host 或-net=host,如果还指定了-p 映射端口,那这个时候就会有此警告,并且通过-p 设置的参数将不会起到任何作用,端口号会以主机端口号为主,重复时则递增。

解决的办法就是使用 docker 的其他网络模式,例如–network=bridge;或者不用-p 选项,或忽略警告

此时我们用 docker inspect tomcat83 ​查看信息:没有网关和 IP 地址。

"Networks": {
    "host": {
        "IPAMConfig": null,
        "Links": null,
        "Aliases": null,
        "NetworkID": "553d2c47bcaad9d82904e56225e6afae3d5a23379822c9d96ac74170041aad79",
        "EndpointID": "1946b0286e008731cb65b6a30f074d6995dc08936126029bb76ea4665dd3d446",
        "Gateway": "",
        "IPAddress": "",
        "IPPrefixLen": 0,
        "IPv6Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "MacAddress": "",
        "DriverOpts": null
    }
}

进入容器内部看:几乎和宿主机的一样

$ docker exec -it tomcat83 bash

$ ip addr
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever



2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:a4:2c:88 brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global noprefixroute dynamic enp0s3
       valid_lft 84224sec preferred_lft 84224sec
    inet6 fe80::d81a:24b:f174:82f/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever


3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:74:1d:cd brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.242/24 brd 192.168.2.255 scope global noprefixroute dynamic enp0s8
       valid_lft 602624sec preferred_lft 602624sec
    inet6 fe80::3c89:876e:2930:5286/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever


4: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:06:12:45 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever


5: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:06:12:45 brd ff:ff:ff:ff:ff:ff



6: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:94:6e:78:c1 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

没有设置-p 的端口映射了,如何访问启动的 tomcat83 ?直接访问宿主机即可!http://宿主机 IP:8080/

在 CentOS 里面用默认的火狐浏览器访问容器内的 tomcat83 看到访问成功,因为此时容器的 IP 借用主机的,所以容器共享宿主机网络 IP,这样的好处是外部主机与容器可以直接通信。

none

在 none 模式下,并不为 Docker 容器进行任何网络配置,禁用了网络功能,只有 lo 标识(就是 127.0.0.1,本地回环)

也就是说,这个 Docker 容器没有网卡、IP、路由等信息,只有一个 lo,需要我们自己为 Docker 容器添加网卡、配置 IP 等。

启动一个来分析:

docker run -d -p 8084:8080 --network none --name tomcat84 billygoo/tomcat8-jdk8

通过 inspect 查看:没有网关和 IP

$ docker inspect tomcat84 | tail -n 20
"Networks": {
    "none": {
        "IPAMConfig": null,
        "Links": null,
        "Aliases": null,
        "NetworkID": "1ddfe19eb462f6485c00ec56945ce5d1835d4aac20b6229e73a0018176c05ff5",
        "EndpointID": "9b92af07ef5c8c85a0c1218167304a72ac01047af69be44e489d199e1879d260",
        "Gateway": "",
        "IPAddress": "",
        "IPPrefixLen": 0,
        "IPv6Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "MacAddress": "",
        "DriverOpts": null
    }
}

进入容器内看:

$ docker exec -it tomcat84 bash


$ ip addr
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

了解即可,不过多展开

container

新建的容器和已经存在的一个容器共享一个网络 IP 配置而不是和宿主机共享。

新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同

样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。

示意图:

接下来实践下,先创建一个容器:

docker run -d -p 8085:8080 --name tomcat85 billygoo/tomcat8-jdk8

然后创建第二个,并使用第一个容器的网卡,但是报错了:

$ docker run -d -p 8086:8080 --network container:tomcat85 --name tomcat86 billygoo/tomcat8-jdk8
$ docker: Error response from daemon: conflicting options: port publishing and the container type network mode.
See 'docker run --help'.

相当于 tomcat86 和 tomcat85 公用同一个 ip 同一个端口,导致端口冲突

这里我们换个镜像:Alpine 操作系统。Alpine Linux 是一款面向安全的、轻型、独立的、非商业的通用 Linux 发行版,专为追求安全性、简单性和资源效率的用户而设计。 可能很多人没听说过这个 Linux 发行版本,但是经常用 Docker 的朋友可能都用过,因为他小,简单,安全而著称,所以作为、基础镜像是非常好的一个选择,可谓是麻雀虽小但五脏俱全,镜像非常小巧,不到 6M 的大小,所以特别适合容器打包

启动 2 个容器:

docker run -it                             --name alpine1  alpine /bin/sh

新开一个终端,运行第二个:

docker run -it --network container:alpine1 --name alpine2  alpine /bin/sh

接下来验证是否共用搭桥,在两个终端内执行 ip addr​:

$ docker exec -it alpine1 /bin/sh
/ # 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
21: eth0@if22: <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

$ docker exec -it alpine2 /bin/sh
/ # 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
21: eth0@if22: <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

可以看到两个 IP 都是一样的,172.17.0.2。如果 alpine1 被关闭了呢?docker stop alpine1

那么 alpine2 也没有 IP 了:

$ 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

自定义网络

接下来介绍第 5 种:自定义网络

Docker 默认的网络有 3 种:

$ docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
5bd056a8204a   bridge       bridge    local
553d2c47bcaa   host         host      local
1ddfe19eb462   none         null      local

但是我们也可以创建一个网络:

$ docker network create aa_network
9eeb4fd0bf15a59d77bdba7e40594eb30ddd2c2c2ad66df706608a939cd2d193


$ docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
9eeb4fd0bf15   aa_network   bridge    local
5bd056a8204a   bridge       bridge    local
553d2c47bcaa   host         host      local
1ddfe19eb462   none         null      local

为什么需要自定义网络?可以将容器分门别类,在各自的网络中通信。之前我们演示过,Docker 内容器的 IP 是有可能发生变化的

在介绍自定义网络之前,我们再次演示下,不使用自定义网络有什么问题。

为避免干扰,先删除其他容器,再启动两个 Tomcat:

docker run -d -p 8081:8080   --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080   --name tomcat82 billygoo/tomcat8-jdk8

然后我们打开两个终端,分别进入容器:

docker exec -it tomcat81 bash
docker exec -it tomcat82 bash

81 的 IP 信息:172.17.0.2

$ ip addr
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
23: eth0@if24: <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 link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

82 的 IP 信息:172.17.0.3

$ ip addr
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
25: eth0@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

此外,在两个容器内,互相是能 ping 通的,例如 81 能 ping 通 82:

$ ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.030 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.024 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.024 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.026 ms

既然 IP 地址是可能变化的,那么根据 IP 地址来通信是可能会被干扰的,能否通过服务名来 ping 呢?当然是不行的,例如在 81:

$ ping tomcat2
ping: tomcat2: Name or service not known

接下来我们演示,使用自定义网络的话,能不能解决上述问题。

首先自定义桥接网络,自定义网络默认使用的是桥接网络 bridge:

$ docker network create zzyy_network

$ docker network ls
NETWORK ID     NAME           DRIVER    SCOPE
f1c9ebe5d961   bridge         bridge    local
553d2c47bcaa   host           host      local
1ddfe19eb462   none           null      local
daf309d234de   zzyy_network   bridge    local

删除之前的容器,新建容器,加入上一步新建的网络:

docker run -d -p 8081:8080 --network zzyy_network  --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --network zzyy_network  --name tomcat82 billygoo/tomcat8-jdk8

再次打开两个终端,分别进入容器,,并且试试能否 ping 通:

$ docker exec -it tomcat81 bash

$ ping tomcat82
PING tomcat82 (172.18.0.3) 56(84) bytes of data.
64 bytes from tomcat82.zzyy_network (172.18.0.3): icmp_seq=1 ttl=64 time=0.046 ms
64 bytes from tomcat82.zzyy_network (172.18.0.3): icmp_seq=2 ttl=64 time=0.038 ms
64 bytes from tomcat82.zzyy_network (172.18.0.3): icmp_seq=3 ttl=64 time=0.039 ms

可以看到完全能 ping 通。

结论:自定义网络本身就维护好了主机名和 IP 的对应关系( IP 和域名都能通)

link 技术

在过去,Docker 还有一种通信的功能(类似网络),叫做 link,不过已经过时了,不用再去学习,官网文档如下:Legacy container links

The --link​ flag is a legacy feature of Docker. It may eventually be removed. Unless you absolutely need to continue using it, we recommend that you use user-defined networks to facilitate communication between two containers instead of using --link​.

(完)


http://www.kler.cn/a/304624.html

相关文章:

  • DOCKER 镜像基础命令
  • 01:(手撸HAL+CubeMX)时钟篇
  • 字节跳动Android面试题汇总及参考答案(80+面试题,持续更新)
  • 微服务day07
  • HarmonyOS SDK下的实践与探索
  • 冗余连接2 hard题 代随C#写法
  • 判断2个excel文件差异的条数
  • MySQL聚合统计
  • vue等比例缩放页面用于网站,官网
  • CAN数据记录仪与乘用车或者工程车辆OBD口连接注意事项
  • 演示:基于WPF的自绘的中国地铁轨道控件
  • [docker]入门
  • 【H2O2|全栈】关于CSS(4)CSS基础(四)
  • Java 算法:随机抽题
  • 最小堆 + 数学思维(重点) + 快速幂
  • java 自定义简单的线程池
  • Mysql 视图存储过程触发器
  • GD - GD32350R_EVAL - PWM实验和验证3 - EmbeddedBuilder - 无源蜂鸣器 - 用PMOS来控制
  • Android CustomDialog圆角背景不生效的问题
  • 使用 PyCharm 新建 Python 项目详解
  • turbo译码算法MAX, MAX_SCALE and MAX_STAR的比较
  • C 语言中表示对象大小的标准数据类型size_t
  • 备份服务器数据防护策略方法
  • 基于SpringBoot的在线汽车租赁信息管理系统
  • 【Java面试】第十一天
  • 九、外观模式