Skip to content

Docker 网络

提示

清空容器和镜像,初始化 docker 工作环境

bash
# 清除所有容器
docker rm -f $(docker ps -aq)
# 清除所有镜像
docker rmi -f $(docker images -aq)

Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。

Linux 和 Mac 网络的区别

Linux 下 Docker 的网络结构Mac 下 Docker 的网络结构

Docker 在 Mac 中的实现是通过 Hypervisor 创建一个轻量级的虚拟机,然后 将 docker 放入到虚拟机中实现。

Mac OS 宿主机和 Docker 中的容器通过 /var/run/docker.sock 这种 socket 文件来通信,所以在 Mac OS 中 ping 容器的 IP、在容器中 ping 宿主机的 IP 就不通。

可以根据容器名来访问容器。docker 容器中没有 ifconfig 和 ping 命令的解决方案

bash
# 创建并运行tomcat01
docker run -d -P --name tomcat01 tomcat
# 创建并运行tomcat02
docker run -d -P --name tomcat02 --link tomcat01 tomcat

# 查看运行的容器
docker ps
CONTAINER ID   IMAGE     COMMAND                STATUS             PORTS                     NAMES
5c6c70b79546   tomcat    "catalina.sh run"      Up About an hour   0.0.0.0:55002->8080/tcp   tomcat02
649cdbda9f1a   tomcat    "catalina.sh run"      Up 3 hours         0.0.0.0:55000->8080/tcp   tomcat01

# tomcat02 访问 tomcat01
docker exec -it tomcat2 ping tomcat01
PING tomcat01 (172.17.0.2) 56(84) bytes of data.
64 bytes from tomcat01 (172.17.0.2): icmp_seq=1 ttl=64 time=0.135 ms
64 bytes from tomcat01 (172.17.0.2): icmp_seq=2 ttl=64 time=0.757 ms
64 bytes from tomcat01 (172.17.0.2): icmp_seq=3 ttl=64 time=0.441 ms
^C
--- tomcat01 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2025ms

# tomcat01 访问 tomcat02
docker exec -it tomcat01 ping tomcat02
ping: tomcat02: Name or service not known

反向就不可以 ping 通,这是因为–link 的本质是把需要连接的容器名/id 写入启动容器的配置文件中,即增加了一个 ip 和容器名/id 的映射:

bash
docker exec -it tomcat02 cat /etc/hosts
127.0.0.1  localhost
::1  localhost ip6-localhost ip6-loopback
fe00::0  ip6-localnet
ff00::0  ip6-mcastprefix
ff02::1  ip6-allnodes
ff02::2  ip6-allrouters
172.17.0.2  tomcat01 649cdbda9f1a

警告

不推荐使用—-link 方式来让容器之间通信

自定义网络

docker network管理网络。可以使用子命令来创建、检查、列出、删除、修剪、连接和断开网络。

命令描述
docker network connect将容器连接到网络
docker network create创建网络
docker network disconnect断开容器与网络的连接
docker network inspect显示一个或多个网络上的详细信息
docker network ls列出网络
docker network prune删除所有未使用的网络
docker network rm删除一个或多个网络

网络模式

模式描述
bridge桥接网络(docker 默认)
none不配置网络
host仅和主机通信
container容器内网络联通(用得少)

创建网络

docker network create

名称、简写描述
--attachable启用手动容器连接
--aux-address网络驱动程序使用的辅助 IPv4 或 IPv6 地址
--config-from要从中复制配置的网络
--config-only创建仅配置网络
--driver,-d用于管理网络的驱动程序
--gateway主子网的 IPv4 或 IPv6 网关
--ingress创建群路由网状网络
--internal限制对网络的外部访问
--ip-range从子范围分配容器 IP
--ipam-driverIP 地址管理驱动程序
--ipam-opt设置 IPAM 驱动程序特定的选项
--ipv6启用 IPv6 网络
--label在网络上设置元数据
--opt,-o设置特定于驱动程序的选项
--scope控制网络范围
--subnet表示网段的 CIDR 格式的子网
bash
# --net bridge 是启动容器时默认追加的命令,bridge实际就是指docker0
docker run -d -P --name tomcat01 --net bridge tomcat
# 等价于
docker run -d -P --name tomcat01 tomcat

提示

docker0 是默认的,不能通过域名去访问(例如 ping)

创建一个自定义网络

bash
docker network create -d bridge --subnet 192.168.10.0/24 --gateway 192.168.10.1 mybridge
# -d,--driver  设置网络模式: bridge、host、none、container
# --subnet     设置网段及掩码,规划网络
# --gateway    设置网关

docker network ls
NETWORK ID     NAME       DRIVER    SCOPE
60de8834b271   bridge     bridge    local
970764cda59b   host       host      local
44312db3653d   mybridge   bridge    local
23484acd6b58   none       null      local

查看自己创建的网络详情

bash
docker network inspect mybridge
[
    {
        "Name": "mybridge",
        "Id": "44312db3653d46d18292579db0ac2fde9804b9c7b75a03b8a477e1e38834ed14",
        "Created": "2022-05-21T02:28:30.011387633Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.10.0/24",// [!code focus:2]
                    "Gateway": "192.168.10.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

创建容器时,使用刚刚部署的网络配置

bash
docker run -d -P --name tomcat01 --net mybridge tomcat

docker run -d -P --name tomcat02 --net mybridge tomcat

tomcat01 与 tomcat02 互 ping docker 容器中没有 ifconfig 和 ping 命令的解决方案

bash
docker exec -it tomcat01 ping tomcat02
PING tomcat02 (192.168.10.3) 56(84) bytes of data.
64 bytes from tomcat02.mybridge (192.168.10.3): icmp_seq=1 ttl=64 time=0.081 ms
64 bytes from tomcat02.mybridge (192.168.10.3): icmp_seq=2 ttl=64 time=0.446 ms
64 bytes from tomcat02.mybridge (192.168.10.3): icmp_seq=3 ttl=64 time=0.443 ms
--- tomcat02 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2030ms
rtt min/avg/max/mdev = 0.081/0.323/0.446/0.171 ms

docker exec -it tomcat02 ping tomcat01
PING tomcat01 (192.168.10.2) 56(84) bytes of data.
64 bytes from tomcat01.mybridge (192.168.10.2): icmp_seq=1 ttl=64 time=0.061 ms
64 bytes from tomcat01.mybridge (192.168.10.2): icmp_seq=2 ttl=64 time=0.426 ms
64 bytes from tomcat01.mybridge (192.168.10.2): icmp_seq=3 ttl=64 time=0.123 ms
--- tomcat01 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2045ms
rtt min/avg/max/mdev = 0.061/0.203/0.426/0.159 ms

再次查看自己配置的网络

bash
docker network inspect mybridge
[
    {
        "Name": "mybridge",
        "Id": "44312db3653d46d18292579db0ac2fde9804b9c7b75a03b8a477e1e38834ed14",
        "Created": "2022-05-21T02:28:30.011387633Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.10.0/24",// [!code focus:2]
                    "Gateway": "192.168.10.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": { // [!code focus:16]
            "6323d2e693313dade2a8730cdd1475dc3f8ffe175860268cec78e51d671cf462": {
                "Name": "tomcat02",
                "EndpointID": "9b94080a94cfa72c1f4910d2966edebd55f57e9ae41ca99e9bfe4479bae51e28",
                "MacAddress": "02:42:c0:a8:0a:03",
                "IPv4Address": "192.168.10.3/24",
                "IPv6Address": ""
            },
            "9a0759cc2245f1a9ebc5ab69da196a2f1a3b50ae7456d204b2dbcdaa836ac791": {
                "Name": "tomcat01",
                "EndpointID": "d7f1ae0de19a0a1f1086712dd871ca457fc1e9d240d6dfd1dc09fde6b7bba1d9",
                "MacAddress": "02:42:c0:a8:0a:02",
                "IPv4Address": "192.168.10.2/24",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

不同网络的容器相互通信

bash
# 启动一个默认docker0的容器
docker run -P -d --name tomcatA tomcat

# 尝试访问mybridge网络中的容器tomcat01
docker exec -it tomcatA ping tomcat01
ping: tomcat01: Name or service not known

docker exec -it tomcat01 ping tomcatA
ping: tomcatA: Name or service not known

使用docker network connect 网络名称/id 容器名称/id

bash
docker network connect mybridge tomcatA

docker exec -it tomcatA ping tomcat01
PING tomcat01 (192.168.10.2) 56(84) bytes of data.
64 bytes from tomcat01.mybridge (192.168.10.2): icmp_seq=1 ttl=64 time=0.171 ms
64 bytes from tomcat01.mybridge (192.168.10.2): icmp_seq=2 ttl=64 time=0.493 ms
64 bytes from tomcat01.mybridge (192.168.10.2): icmp_seq=3 ttl=64 time=0.398 ms
--- tomcat01 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2006ms
rtt min/avg/max/mdev = 0.171/0.354/0.493/0.135 ms

docker exec -it tomcat01 ping tomcatA
PING tomcatA (192.168.10.4) 56(84) bytes of data.
64 bytes from tomcatA.mybridge (192.168.10.4): icmp_seq=1 ttl=64 time=0.046 ms
64 bytes from tomcatA.mybridge (192.168.10.4): icmp_seq=2 ttl=64 time=0.489 ms
64 bytes from tomcatA.mybridge (192.168.10.4): icmp_seq=3 ttl=64 time=0.550 ms
--- tomcatA ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2069ms
rtt min/avg/max/mdev = 0.046/0.361/0.550/0.224 ms

查看自定义的网络详情

bash
docker network inspect mybridge
[
    {
        "Name": "mybridge",
        "Id": "44312db3653d46d18292579db0ac2fde9804b9c7b75a03b8a477e1e38834ed14",
        "Created": "2022-05-21T02:28:30.011387633Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.10.0/24",// [!code focus:2]
                    "Gateway": "192.168.10.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {// [!code focus:23]
            "6323d2e693313dade2a8730cdd1475dc3f8ffe175860268cec78e51d671cf462": {
                "Name": "tomcat02",
                "EndpointID": "9b94080a94cfa72c1f4910d2966edebd55f57e9ae41ca99e9bfe4479bae51e28",
                "MacAddress": "02:42:c0:a8:0a:03",
                "IPv4Address": "192.168.10.3/24",
                "IPv6Address": ""
            },
            "9a0759cc2245f1a9ebc5ab69da196a2f1a3b50ae7456d204b2dbcdaa836ac791": {
                "Name": "tomcat01",
                "EndpointID": "d7f1ae0de19a0a1f1086712dd871ca457fc1e9d240d6dfd1dc09fde6b7bba1d9",
                "MacAddress": "02:42:c0:a8:0a:02",
                "IPv4Address": "192.168.10.2/24",
                "IPv6Address": ""
            },
            "c6b36ce3b56c3bc419ebbe26c71ded6cd5c98a5b876e8b14004854b2d3987d93": {
                "Name": "tomcatA",
                "EndpointID": "8efcff9c213aca4e4e5897aaaef3a85478a94473c2b7be82e789361df6387ca3",
                "MacAddress": "02:42:c0:a8:0a:04",
                "IPv4Address": "192.168.10.4/24",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

实际上原理为给单个容器添加多个 IP来实现不同网络中的容器通信

扩展

将正在运行的容器连接到网络

bash
docker network connect mybridge tomcatA

在启动容器时,将容器连接到网络

bash
docker run -itd --net mybridge tomcat

指定要分配给容器接口的 IP 地址(请确保 IP 可用

bash
docker network connect --ip 192.168.10.10 mybridge tomcatA