欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

docker容器间的联网

程序员文章站 2022-06-03 14:26:12
...

翻译自docker官方文档,原文:https://docs.docker.com/engine/tutorials/networkingcontainers/

如果你是顺着用户指南读到这的,那么你刚刚构建并运行起来了一个简单的应用。你也构建了你自己的镜像。本节将教你如何让你的容器通过网络连接起来。

在默认网络中启动容器

docker支持通过网络驱动器来将容器互联。Docker默认提供两种网络驱动:bridge和overlay。你也可以自己写一个网络驱动插件来创建你自己的网络驱动,但这是更高阶的话题了。
Docker引擎安装后默认就有三个网络,你可以列出它们:

$ docker network ls

NETWORK ID          NAME                DRIVER
18a2866682b8        none                null
c288470c46f6        host                host
7b369448dccb        bridge              bridge

叫做bridge的网络是特殊的,docker总是把你的容器加入这个网络,除非你明确指定不要这样做。尝试下面的命令:

$ docker run -itd --name=networktest ubuntu

74695c9cea6d9810718fddadc01a727a5dd3ce6a69d09752239736c030599741

docker容器间的联网
检查(inspect)网络是一种查看容器IP地址的简单方式:

$ docker network inspect bridge

[
    {
        "Name": "bridge",
        "Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.1/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Containers": {
            "3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c": {
                "Name": "networktest",
                "EndpointID": "647c12443e91faf0fd508b6edfe59c30b642abb60dfab890b4bdccee38750bc1",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "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": "9001"
        },
        "Labels": {}
    }
]

你可以通过断连接(disconnect)容器来把容器从一个网络中移除。要做这件事,你要指定网络名称和容器名,也可以用容器ID代替。在本例中,用名字更快:

$ docker network disconnect bridge networktest

虽然你可以把一个容器从一个网络中移除,但你不能移除内置的bridge式网络“bridge”。网络是把容器和其他容器或网络进行隔离的原生的方式。所以,随着你使用docker的经验增加,你会想要创建你自己的网络的。

创建你自己的bridge式网络

docker引擎原生就支持bridge式和overlay式的网络。bridge式网络只能在运行docker引擎的单主机上运行。Overlay式网络可以包含多个宿主机并且是个更高阶的话题。在本例中,你将创建一个bridge式网络:

$ docker network create -d bridge my_bridge

-d标志告诉docker使用bridge驱动来创建新网络。你也可以省略这个标志,因为bridge式这个标志的默认值。继续并列出你机器上的所有网络:

$ docker network ls

NETWORK ID          NAME                DRIVER
7b369448dccb        bridge              bridge
615d565d498c        my_bridge           bridge
18a2866682b8        none                null
c288470c46f6        host                host

如果你检查(inspect)刚创建的这个网络,你会发现它里面什么也没有:

$ docker network inspect my_bridge

[
    {
        "Name": "my_bridge",
        "Id": "5a8afc6364bccb199540e133e63adb76a557906dd9ff82b94183fc48c40857ac",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Config": [
                {
                    "Subnet": "10.0.0.0/24",
                    "Gateway": "10.0.0.1"
                }
            ]
        },
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

把容器加入网络

要安全地创建多个需要通信的网络应用,那就创建一个网络。网络,被定义成给容器提供完全的隔离。你可以在第一次启动容器时就把它加入一个网络。
启动一个运行PostgreSQL数据库的容器并传--net=my_bridge参数给它,以使他连到你新创建的网络上:

$ docker run -d --net=my_bridge --name db training/postgres

如果你检查(inspect)你的my_bridge网络,你会发现有一个容器附上了。你也可以检查你的容器来查看它连到那个网络上了:

$ docker inspect --format='{{json .NetworkSettings.Networks}}'  db


{"my_bridge":{"NetworkID":"7d86d31b1478e7cca9ebed7e73aa0fdeec46c5ca29497431d3007d2d9e15ed99",
"EndpointID":"508b170d56b2ac9e4ef86694b0a76a22dd3df1983404f7321da5649645bf7043","Gateway":"10.0.0.1","IPAddress":"10.0.0.254","IPPrefixLen":24,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:11:00:02"}}

现在,启动你已经很熟悉的“web”应用。这次不要指定网络:

$ docker run -d --name web training/webapp python app.py

docker容器间的联网
你的”web”应用运行在哪个网络下呢?检查应用你就会发现它运行在默认的bridge网络下:

$ docker inspect --format='{{json .NetworkSettings.Networks}}'  web


{"bridge":{"NetworkID":"7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812",
"EndpointID":"508b170d56b2ac9e4ef86694b0a76a22dd3df1983404f7321da5649645bf7043","Gateway":"172.17.0.1","IPAddress":"10.0.0.2","IPPrefixLen":24,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:11:00:02"}}

现在,获取你的“web”应用的IP地址:

$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web


172.17.0.2

现在,在正在运行的db容器中启动一个shell:

$ docker exec -it db bash

aaa@qq.com:/# ping 172.17.0.2
ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
^C
--- 172.17.0.2 ping statistics ---
44 packets transmitted, 0 received, 100% packet loss, time 43185ms

等一会后按CTRL-C 来终止ping操作,你会发现ping失败了。因为两个容器在不同的网络下运行着。你可以修复它。现在,用exit命令来关闭容器。
docker网络允许你把一个容器连到多个网络中。你也可以对正在运行的容器进行这种操作。现在把你的正在运行的“web”应用连到my_bridge上:

$ docker network connect my_bridge web

docker容器间的联网
在db应用中启动一个shell并在此尝试ping操作。这次用容器名字“web”而不要用IP地址:

$ docker exec -it db bash

aaa@qq.com:/# ping web
PING web (10.0.0.2) 56(84) bytes of data.
64 bytes from web (10.0.0.2): icmp_seq=1 ttl=64 time=0.095 ms
64 bytes from web (10.0.0.2): icmp_seq=2 ttl=64 time=0.060 ms
64 bytes from web (10.0.0.2): icmp_seq=3 ttl=64 time=0.066 ms
^C
--- web ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.060/0.073/0.095/0.018 ms

命令结果显示它在连接一个不同的IP地址。Web容器在my_bridge中的IP地址和它在bridge网络中的IP地址是不同的。

下一步

现在你知道了如何让容器互联,接下来请看如何管理容器中的数据。

译者注:如上所示,在同一网络内的两个容器可以通过容器名来进行通信,但容器内的hosts文件中并没有配置容器名和容器IP间的映射关系,目前猜想是docker用来管理网络的模块实现了一种类似DNS服务的机制,维护了容器名和IP的映射关系,容器间的IP查找都通过该服务。另外,docker run 命令中的--link 参数的具体作用是什么,也有待研究。

相关标签: docker 联网