Docker 容器之间通过名字相互访问

docker 网卡介绍

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

[root@192 ~] docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
ad4b81d87e1b        bridge              bridge              local
1f5e4e4ec3e7        host                host                local
0d3f684a5dba        none                null                local
  • bridge 是默认的网卡,网络驱动是 bridge 模式,类似于 Vmware 的 NAT 模式,如果容器启动时不指定网卡,则会默认连接到这块网卡上。如果需要访问容器内部的端口需要设置端口映射。
  • host 是直接使用主机的网络,网络驱动是 host 模式,类似于 Vmware 的桥接模式,可能会和主机的端口存在冲突,不需要设置端口映射即可连接到容器端口。
  • none 禁止所有联网,没有网络驱动,一般情况下用不到。
    由于默认的网卡需要设置端口映射并且 IP 地址会随着容器的启动停止而变动,所以我们这里选择使用自定义网络来实现容器之间互相访问。

创建自定义网络

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

[root@192 ~] docker network create mysql-cluster
8a2f490df6bf8def08d3bbd91ed411315c8afd717bc75e77504248712ec47a78
[root@192 ~] docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
ad4b81d87e1b        bridge              bridge              local
1f5e4e4ec3e7        host                host                local
8a2f490df6bf        mysql-cluster       bridge              local
0d3f684a5dba        none                null                local

现在这个创建好的自定义网络就和默认的 bridge 网络隔离开了,互相之间不能访问,而且它们也不在同一个网段上。
使用 docker network inspect bridge 命令查看默认网卡的详细信息。

语法

docker network create [OPTIONS] NETWORK

选项

名称,简写 默认 说明
--attachable false API 1.25+,启用手动容器安装
--aux-address map[] Network驱动程序使用的辅助 IPv4 或 IPv6 地址
--driver, -d bridge 驱动程序管理网络
--gateway 用于主子网的 IPv4 或 IPv6 网关
--internal false 限制对网络的外部访问
--ip-range 从子范围分配容器 ip
--ipam-driver default IP 地址管理驱动程序
--ipam-opt map[] 设置 IPAM 驱动程序的具体选项
--ipv6 false 启用 IPv6 网络
--label 在网络上设置元数据
--opt, -o map[] 设置驱动程序特定选项
--subnet 表示网段的 CIDR 格式的子网,代表网络段
--config-from API 1.30+,从中复制配置的网络
--config-only API 1.30+,仅创建配置网络
--ingress API 1.29+,创建Swarm路由网格网络
--scope API 1.30+,控制网络的范围

自定义网络

  • 自定义网络模式,docker 主要提供了三种自定义网络驱动:
    • bridge
    • overlay
    • macvlan
      bridge 驱动类似默认的 bridge 网络模式,但增加了一些新的功能,overlay 和 macvlan 是用于创建跨主机网络
  • 建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动 DNS 解析容器名称到 IP地址。

示例

docker network create --driver bridge --subnet=172.18.12.0/16 --gateway=172.18.1.1 mynet
  • --driver bridge 表示使用桥接模式
  • --subnet 172.18.12.0/16 表示子网ip 可以分配 172.18.1.2 到 172.18.255.255
  • --gateway 172.18.1.1 表示网关
  • mynet 表示网络名

示例

创建容器

创建两个 python 容器,使用 docker run -it --name test1 --network my-net python bash 命令来创建第一个名字为 test1 的容器,--name 参数指定容器的名字,--network 参数指定使用自定义的网络, 然后开启一个 python 自带的 HTTP Server。

[root@192 ~] docker run -it --name test1 --network my-net python bash
root@0136e7769fc4:  python -m http.server
 Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

新开启一个终端,使用 docker run -it --name test2 --network my-net python bash 命令创建第二个名字为 test2 的容器,尝试使用 curl 通过别名 test1 来访问第一个容器。

 [root@192 ~] docker run -it --name test2 --network my-net python bash
 root@fdbc076a6753:/ curl test1:8000
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <title>Directory listing for /</title>
 </head>
 <body>
 <h1>Directory listing for /</h1>
 <hr>
 <ul>
 <li><a href=".dockerenv">.dockerenv</a></li>
 <li><a href="bin/">bin/</a></li>
 <li><a href="boot/">boot/</a></li>
 <li><a href="dev/">dev/</a></li>
 <li><a href="etc/">etc/</a></li>
 <li><a href="home/">home/</a></li>
 <li><a href="lib/">lib/</a></li>
 <li><a href="lib64/">lib64/</a></li>
 <li><a href="media/">media/</a></li>
 <li><a href="mnt/">mnt/</a></li>
 <li><a href="opt/">opt/</a></li>
 <li><a href="proc/">proc/</a></li>
 <li><a href="root/">root/</a></li>
 <li><a href="run/">run/</a></li>
 <li><a href="sbin/">sbin/</a></li>
 <li><a href="srv/">srv/</a></li>
 <li><a href="sys/">sys/</a></li>
 <li><a href="tmp/">tmp/</a></li>
 <li><a href="usr/">usr/</a></li>
 <li><a href="var/">var/</a></li>
 </ul>
 <hr>
 </body>
 </html>

成功返回了 test1 容器的根目录内容,使用 ping 命令测试也是可以正常 ping 的通的。

 root@fdbc076a6753:/ ping test1
 PING test1 (172.18.0.2) 56(84) bytes of data.
 64 bytes from test1.my-net (172.18.0.2): icmp_seq=1 ttl=64 time=0.054 ms
 64 bytes from test1.my-net (172.18.0.2): icmp_seq=2 ttl=64 time=0.084 ms
 ^C
 --- test1 ping statistics ---
 2 packets transmitted, 2 received, 0% packet loss, time 27ms
 rtt min/avg/max/mdev = 0.054/0.069/0.084/0.015 ms

由于在创建容器时并没有使用 -p 参数设置端口映射,所以外部不能访问到容器内部的内容,但是容器之间全端口都是可以正常访问的。

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

默认的网卡的网卡驱动也是 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 文件的方式来指定解析结果,但是这样将会非常难以调试。

posted @   Thousand_Mesh  阅读(60)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示