Docker系列:容器网络

145 阅读3分钟

由于容器的隔离性,它们不共享主机网络,但 Docker 为它们提供了网络

当 Docker 运行时启动时,它会创建 3 个默认网络:

$ docker network ls

NETWORK ID     NAME      DRIVER    SCOPE
5c65c2b3031b   bridge    bridge    local
cf446ef29441   host      host      local
50fd86384bb9   none      null      local

image.png

桥接网络

image.png

首先,我们可以通过检查网络来检查配置:

$ docker network inspect bridge

[
    {
        "Name": "bridge",
        "Id": "5c65c2b3031b6d10f357f74f6cb5bf04af13819fca28b5458e00bb6b1d1718ec",
        "Created": "2022-06-27T23:49:43.227773167Z",
        "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": {}
    }
]

我们可以看到网络通过Gateway 172.17.0.1进行响应,此时没有添加容器。

桥接网络提供桥接驱动程序,以便在此网络中创建的容器接收IP 地址

为了确认这一点,我们创建一个 NGINX 容器:

$ docker run --name nginx --network bridge -d nginx

它只是一个在容器端口上运行的 NGINX Web 应用程序80,并提供传统的 HTML 页面“欢迎来到 NGINX”。 容器是否已添加到网络中?

$ docker network inspect bridge

...
        "Containers": {
            "bb283ee626dbc631281fc0c27a1f02f075ab1908800965008a315cedd7f9d438": {
                "Name": "nginx",
                "EndpointID": "f12f67c1d7488f708027c2e948b204ce09743721095d4514c9c24bedf8167191",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },

我们可以看到最近创建的容器已添加到bridge网络中并获得了 IP 地址172.17.0.2。 我们如何使用它的 IP 与这样的容器进行通信,换句话说,我们可以点击http://172.17.0.2并看到“Welcome to NGINX”HTML 结果吗?

$ wget http://172.17.0.2 -O -
Connecting to 172.17.0.2:80...

容器不共享主机网络

同样,容器不共享“主机”网络。这意味着只有同一网络(网桥)中的其他容器才能相互通信。

好的,我们可以运行另一个容器并访问 NGINX 吗?

$ docker run \
    --network bridge \
    alpine \
    sh -c "wget http://172.17.0.2 -O -"

Connecting to 172.17.0.2 (172.17.0.2:80)
writing to stdout
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
-                    100% |********************************|   615  0:00:00 ETA
written to stdout

Bridge 已经是默认网络

只是为了节省时间,每当我们创建容器时,它们都会自动添加到网络中bridge

主机网络

image.png

当我们需要将容器暴露给主机网络时,这个网络非常有用。 host模式主要用于对网络性能要求高、追求传输效率的服务,但是需要注意的是会占用主机的端口,多个容器工作可能需要处理冲突。

$ docker --name nginx --network host -d nginx
$ docker network inspect host

[
    {
        "Name": "host",
        "Id": "cf446ef29441aeaaee2a40cfcf9ad120aedb7c51cf2dbc20cc23e567101d217c",
        "Created": "2022-01-13T21:57:00.2326735Z",
        "Scope": "local",
        "Driver": "host",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": []
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "668c12bbabb8cd28e8cc8666d074fc929214f7b9ddfddfa3d76c8476652c4091": {
                "Name": "nginx",
                "EndpointID": "738ea09ee3d450e9f655440a303a52f219d9ca22fe011eb62dffe7d0351f31de",
                "MacAddress": "",
                "IPv4Address": "",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

我们可以看到容器添加到网络中,但它没有 IP 地址,这意味着其他容器无法与它通信,只能与主机通信。

# Linux only
$ wget http://localhost -O -

注意:该网络仅适用于 Linux。在 Mac 或 Windows 的 Docker Desktop 中,我们必须使用另一种方式将容器暴露给主机

-p 选项

将容器暴露给主机的另一种方法是使用 flag ,它本身-p不是主机网络,但它将 [container port] 发布到 [host port]

$ docker run --name nginx -p 80:80 -d nginx
$ wget http://localhost -O -

无网络

任何时候我们需要创建一个完全隔离的容器,与任何其他容器通信,我们都可以将其添加到none使用驱动程序的网络中null

$ docker run --name nginx --network none -d nginx
$ docker network inspect none

[
    {
        "Name": "none",
        "Id": "50fd86384bb9cc90d953a624a5ab70b869357027d3cdc7ebc9b4043798dd4f6a",
        "Created": "2022-01-13T21:57:00.224557375Z",
        "Scope": "local",
        "Driver": "null",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": []
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "90a6691b818e164bd2e1f67e8f3a62ce71eaddbe9ac215c370a8a6766204a2b0": {
                "Name": "nginx",
                "EndpointID": "0ed9e33f051f2df2c37b96fc2fdf7df074b73359117a12a81ae4c28ef0ec6877",
                "MacAddress": "",
                "IPv4Address": "",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

该网络没有网关 IP,因此不要将IP 地址与容器关联。