两个或多个docker容器之间通过名字相互访问

前言

需要部署的项目中有数据库和 Tomcat,Tomcat需要连接到数据库容器的 3306 端口上,由于容器的 IP 地址会变化,又不能写死 IP 地址,所以就有了下文。

docker 网卡介绍

docker 安装好之后默认会创建三个虚拟网卡,可以使用 docker network ls 命令来查看,三个虚拟网卡和 VMware 的类似。

mango@wanzhouyi:~$ sudo docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
a831f74e2810   bridge    bridge    local
1d49e8d7b613   es_test   bridge    local
72e00f5290f2   host      host      local
5eb25bd2cd37   none      null      local
mango@wanzhouyi:~$
  • bridge 是默认的网卡,网络驱动是 bridge 模式,类似于 Vmware 的 NAT 模式,如果容器启动时不指定网卡,则会默认连接到这块网卡上。如果需要访问容器内部的端口需要设置端口映射。
  • host 是直接使用主机的网络,网络驱动是 host 模式,类似于 Vmware 的桥接模式,可能会和主机的端口存在冲突,不需要设置端口映射即可连接到容器端口。
  • none 禁止所有联网,没有网络驱动,一般情况下用不到。

由于默认的网卡需要设置端口映射并且 IP 地址会随着容器的启动停止而变动,所以我们这里选择使用自定义网络来实现容器之间互相访问。

创建自定义网络

使用 docker network create my-net 命令来创建一个我们自定义的网络,网络驱动仍然使用 bridge。

mango@wanzhouyi:~$ sudo docker network create my-net
cdf381aba9901c18c31b02cf8c6046b61e1c973bddf64d8469f1c18830a07093
mango@wanzhouyi:~$ sudo docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
a831f74e2810   bridge    bridge    local
1d49e8d7b613   es_test   bridge    local
72e00f5290f2   host      host      local
cdf381aba990   my-net    bridge    local
5eb25bd2cd37   none      null      local
mango@wanzhouyi:~$

现在这个创建好的自定义网络就和默认的 bridge 网络隔离开了,互相之间不能访问,而且它们也不在同一个网段上。

使用 docker network inspect bridge 命令查看默认网卡的详细信息。

mango@wanzhouyi:~$ sudo docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "a831f74e2810f7945fc277610dd963e0875c5139916c4784ad5631c7a852247b",
        "Created": "2022-10-11T23:44:25.4523466+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"
                }
            ]
        },

使用 docker network inspect my-net 命令查看自定义网卡的详细信息。

mango@wanzhouyi:~$ sudo docker network inspect my-net
[
    {
        "Name": "my-net",
        "Id": "cdf381aba9901c18c31b02cf8c6046b61e1c973bddf64d8469f1c18830a07093",
        "Created": "2022-10-12T01:54:05.6933414+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.20.0.0/16",
                    "Gateway": "172.20.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

对比一下可以看出,默认网卡处于 172.17.0.0/16 这个网段,自定义网卡处于 172.20.0.0/16 这个网段,它们两个肯定是不可以互相通信的。

默认网络和自定义网络区别

说到这里可能有人会问了,那默认的网卡的网卡驱动也是 bridge 模式的,用户自定义的网络也是 bridge 模式,不就是换了一个名字吗,为什么默认的网卡不可以使用别名进行 IP 地址解析呢?

这个问题问得好,官方特意解释了这两个网卡的区别。

User-defined bridges provide automatic DNS resolution between containers.
Containers on the default bridge network can only access each other by IP addresses, unless you use the --link option, which is considered legacy. On a user-defined bridge network, containers can resolve each other by name or alias.
翻译过来大意:就是用户自定义的网卡可以在容器之间提供自动的 DNS 解析,缺省的桥接网络上的容器只能通过 IP 地址互相访问,除非使用 --link 参数。在用户自定义的网卡上,容器直接可以通过名称或者别名相互解析。

文档中提到了 --link 参数,官方文档中已经不推荐使用 --link 参数,并且最终可能会被删除,所以最好不要使用 --link 参数来连接两个容器,并且它有多个缺点。

如果使用 --link 参数,需要在容器之间手动创建链接,这些链接需要双向创建,如果容器多于两个的话,将会很困难。或者也可以通过编辑 hosts 文件的方式来指定解析结果,但是这样将会非常难以调试。

总结
以上就是通过自定义网卡来使两个容器互相连接的方法,这种方法便于部署和调试,而且还提供了网络隔离功能,两个容器之间不会互相干扰,可以随时断开或者连接,并且可以使用 --subnet 参数指定自定义网络的 IP 段,这里就不详细展开了。

posted @ 2022-10-12 02:00  周XX  阅读(1144)  评论(0编辑  收藏  举报