目录
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 文件的方式来指定解析结果,但是这样将会非常难以调试。