一: Docker 默认的网络模型
Docker Host : 安装了 docker deamon 的主机
docker0 : 安装了 docker 之后出现的网桥
通过网桥可以将 Linux 支持的不同的端口连接起来
实现类交换机多对多的通信
veth pair
虚拟以太网(Ethernet)设备
成对出现,用于解决网络命名空间之间的隔离
一端连接 Container network namespace,另一端连接 host network namespace
当创建了一个容器之后 , 会在主机中创建一个虚拟的以太网设备 ( veth )
一端连接主机的网络的命名空间
一端连接容器的网络命名空间
启动一个容器,查看容器的网络设备
docker run -it centos:latest bash
可以看到容器有自己的网络设备,这是连接容器网络命名空间的一端
按住ctrl+p+q
退回容器,使容器在后台运行
这个虚拟的网络设备就是连接 docker host 网络命名空间的
二: Docker 网络模型工作原理
1. 容器访问外网
容器中的数据包转发给 eth0 网卡,然后在转发到 docker host 命名空间的虚拟网络设备,虚拟的网络设备会把数据传给 docker0, 然后再转发给 eth0 ( 物理网卡 ),
SNAT 源地址转换:把 docker0 的源地址转换成 docker host 主机所在网段的 IP 地址
iptables -t nat -vnL POSTROUTING
MASQUERADE 就是 SNAT ,底层转发是由 iptables 来承载的
2. 外网访问容器
首先外网的数据包能够传送到 eth0 网卡,内核接收到数据之后会进行 DNAT (目标地址转换)
所以容器的 port 就是: 但访问宿主主机的 3306 端口,会被转发到容器的某个端口
可以通过 iptables 看到 docker 链
iptables -t nat -nL
不管哪个 IP , 不管目标地址是哪个,只要访问对应端口,就转换到 172.17.... 的对应端口
三: Docker 四种网络模型
bridge [ 桥接式网络 ( Bridge container A ) ]:
--network bridge
(默认网络模型)桥接容器,除了有一块本地回环接口 ( Loopback interface ) 外,还有一块私有接口 ( Private interface ) 通过容器虚拟接口 ( Container virtual interface ) 连接到桥接虚拟接口 ( Docker bridge virtual interface ),之后通过逻辑主机接口 ( Logical host interface ) 连接到主机物理网络 ( Physical network interface )。桥接网卡默认会分配到 172.17.0.0/16 的IP地址段。
如果我们在创建容器时没有指定网络模型,默认就是 ( Nat ) 桥接网络,这也就是为什么我们在登录到一个容器后,发现 IP 地址段都在 172.17.0.0/16 网段的原因。
容器通过虚拟以太网设备连接到主机的网络命名空间,通过主机的命名空间实现对外网的访问
host [ 开放式容器 ( Open container ) ]:
--network host
比联盟式网络更开放,联盟式网络是多个容器共享网络 ( Net ) , 而开放式容器 ( Open contaner ) 就直接共享了宿主机的名称空间。因此物理网卡有多少个,那么该容器就能看到多少网卡信息。我们可以说 Open container 是联盟式容器的衍生。
让容器和主键共享同一个网络命名空间,容器中的 IP 地址和 Docker host IP 地址是完全一直的,有利于对容器服务的访问
none [封闭式网络(Closed container)]:
--network none
封闭式容器,只有本地回环接口 ( Loopback interface ) ,和服务器看到的 lo 接口类似),无法与外界进行通信。
这种网络模式中只有 Loopback 这种网路接口,不能去连接外网
container [联盟式网络 ( Joined container A | Joined container B ]:
--network container:c1(容器名称或容器ID)
每个容器都各有一部分名称空间 ( Mount , PID , User ),另外一部分名称空间是共享的( UTS , Net , IPC ) 。由于它们的网络是共享的,因此各个容器可以通过本地回环接口 ( Loopback interface ) 进行通信。除了共享同一组本地回环接口 ( Loopback interface ) 外,还有一块一块私有接口 ( Private interface ) 通过联合容器虚拟接口 ( Joined container virtual interface )连接到桥接虚拟接口 ( Docker bridge virtual interface ),之后通过逻辑主机接口 ( Logical host interface ) 连接到主机物理网络 ( Physical network interface )。
可以共享两个容器的命名空间
五: 查看指定类型的网络模型
1. 查看所有容器的网络模型
# 查看已有的网络模型
docker network ls
docker netword list
2. 查看指定网络模型的详细信息
root@VM-8-13-debian:~# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "6e7985ab54cdd0f9143da410b03f5e0df82146d3e0256fee573e6d3c64de4df5",
"Created": "2023-10-12T18:42:05.876320519+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"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
# 哪些容器连接到了这个网络
"Containers": {
"420df0739e938ad67819430697329aa0cd0b9dc83be296995bfdf3a90b74b6e7": {
"Name": "etcd",
"EndpointID": "52e9e6d2601301c87c5dcaa2d8cfd47e2da9317692d2572e201207e98ca03a3c",
# 容器的IP地址和MAC地址
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"e01f2b3407cb1962b15630623e7d4ecd1ac2e40e256e3d2d87390dd31ef38985": {
"Name": "quizzical_nobel",
"EndpointID": "560ab4c4cf83a011fdeec12e2ac3e3b0c4252a7cb81a5ae115067ba82eea9dfb",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
}
},
# 默认选项
"Options": {
# 是不是默认网桥
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
# 是否开启上网功能(源地址转换 SNAT)
"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": {}
}
]
3. 查看 docker 支持的网络模型
root@VM-8-13-debian:~# docker info | grep Network
Network: bridge host ipvlan macvlan null overlay
六: 创建指定类型的网络模型
1. bridge
查看帮助
docker network create -h
创建网络模型
# 1.简单写法
docker network create Mysql
# 2.复杂写法
docker network create -d bridge --subnet "192.168.100.0/24" --gateway "192.168.100.1" -o com.docker.network.bridge.name=docker1 Mysql
# com.docker.network.bridge.name 就是上面查看网络模型选项信息里面的内容
验证是否创建成功
root@VM-8-13-debian:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
b14e183c0386 1panel-network bridge local
136c9c1912fc Mysql bridge local
d60f5e7ed7e9 backend_default bridge local
6e7985ab54cd bridge bridge local
affe2ac83252 host host local
20037e8c62b7 kafka_default bridge local
df9f2ca51637 logs_default bridge local
aeecc2524ba4 none null local
# 同时也可以使用 docker network inspect Mysql查看详细信息
启动一个容器连接到创建的网络
# docker run -it --network Mysql busybox
/ # ping wwww.baidu.com
PING wwww.baidu.com (110.242.68.66): 56 data bytes
64 bytes from 110.242.68.66: seq=0 ttl=250 time=10.616 ms
64 bytes from 110.242.68.66: seq=1 ttl=250 time=10.601 ms
64 bytes from 110.242.68.66: seq=2 ttl=250 time=10.595 ms
--- wwww.baidu.com ping statistics ---
11 packets transmitted, 11 packets received, 0% packet loss
round-trip min/avg/max = 10.589/10.612/10.628 ms
可以看出是可以正常 ping 通的
2. host
docker run -it --network host --rm busybox
# 启动Nginx 服务
docker run -d --network host nginx:latest
查看容器运行状态
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f6677b213271 nginx:latest "/docker-entrypoint.…" 7 seconds ago Up 6 seconds youthful_shtern
查看docker host 80端口状态
# ss -anput | grep ":80"
tcp LISTEN 0 511 *:80 *:* users:(("nginx",pid=42866,fd=7),("nginx",pid=42826,fd=7))
tcp LISTEN 0 511 :::80 :::* users:(("nginx",pid=42866,fd=8),("nginx",pid=42826,fd=8))
host 网络模型用的是和宿主主机同一个命名空间
缺点: 无法启动第二个这样的容器 ( 端口很稀缺 )
3. none
root@VM-8-13-debian:~# docker run -it --network none busybox
/ # ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
可以看到是没有网络的,如果连接了只能在本地做一下测试
如果需要有更多的网络,可以创建虚拟的网络设备
4. 联盟网络
创建c1容器,使用默认网络模型
root@VM-8-13-debian:~# docker run -it --name c1 --rm busybox:latest
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03
inet addr:172.17.0.3 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:516 (516.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
创建c2容器,与c1容器共享网络命名空间
root@VM-8-13-debian:~# docker run -it --name c2 --network container:c1 --rm busybox:latest
root@VM-8-13-debian:~# docker run -it --name c2 --network container:c1 --rm busybox:latest
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03
inet addr:172.17.0.3 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:11 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:866 (866.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
可以看到两者的虚拟网卡一模一样
# 在c2容器中创建文件并开启httpd服务
echo "hello world" >> /tmp/index.html
ls /tmp
index.html
httpd -h /tmp
# 验证80端口是否打开
/ # netstat -npl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 :::80 :::* LISTEN 10/httpd
# 在c1容器中进行访问验证
docker exec c1 wget -O - -q 127.0.0.1
hello world
网络共享,文件系统独立
评论区