Torres-tao  

Docker网络

1、Docker网络实现原理

Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),docker启动一个容器时会根据docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。

因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能通过容器的Container-IP直接通信。

Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法直接通过Container-IP访问到容器。

如果容器希望能被外部访问,可通过映射容器端口到宿主机(端口映射),即docker run创建容器的时候通过-p或-P参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。

1.1、随机映射端口

[root@aliyun ~]# docker run -d -P --name nginx01 nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete
a9edb18cadd1: Pull complete
589b7251471a: Pull complete
186b1aaa4aa6: Pull complete
b4df32aa5a72: Pull complete
a0bcbecc962e: Pull complete
Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Status: Downloaded newer image for nginx:latest
2ddb5c52db610939452531a3635e5eda6561e639a945f4ca749c3bc46f95de0d
[root@aliyun ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2ddb5c52db61 nginx "/docker-entrypoint.…" 7 seconds ago Up 7 seconds 0.0.0.0:49157->80/tcp nginx01

1.2、指定映射端口

[root@aliyun ~]# docker run -d -p 8088:80 --name nginx02 nginx
823ae713d67ba3771351161d0201528fe072c6c733c9b4acf90abc7324656dfa
[root@aliyun ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
823ae713d67b nginx "/docker-entrypoint.…" 7 seconds ago Up 6 seconds 0.0.0.0:8088->80/tcp nginx02
2ddb5c52db61 nginx "/docker-entrypoint.…" 39 seconds ago Up 38 seconds 0.0.0.0:49157->80/tcp nginx01

1.3、访问测试

#8088端口
[root@aliyun ~]# curl localhost:8088
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
#49157端口
[root@aliyun ~]# curl localhost:49157
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

查看iptables规则

[root@aliyun ~]# iptables -nL -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.18.0.0/16 0.0.0.0/0
MASQUERADE tcp -- 172.18.0.2 172.18.0.2 tcp dpt:80
MASQUERADE tcp -- 172.18.0.3 172.18.0.3 tcp dpt:80
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:49157 to:172.18.0.2:80
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8088 to:172.18.0.3:80

2、Docker网络模式

  1. Host:容器不会虚拟出自己的网卡,配置主机的IP等,而是使用宿主机的IP和端口
  2. Container:创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围
  3. None:该模式关闭了容器的网络功能
  4. Bridge:默认为该模式,此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0的虚拟网桥,通过docker0网桥以及iptables nat表配置与宿主机通信
  5. 自定义网络

2.1、默认网络

当安装docker时,它会自动创建三个网络bridge(创建容器默认连接到此网络)、none、host。可使用docker network ls查询

[root@aliyun ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
8df3cdb08d2a bridge bridge local
c3009610274a host host local
e6d7cbd64aa7 none null local

2.2、容器网络模式指定

使用docker run创建docker容器时,可以用--net或--network选项指定容器的网络模式:

  • host模式:使用--net=host指定
  • none模式:使用--net=none指定
  • container模式:使用--net=container:NAME__or_ID指定
  • bridge模式:使用--net=bridge指定,默认配置,可省略

3、Docker网络模式详解

3.1、host模式

host模式相当于VMware中的桥接模式,与宿主机在同一个网络中,但是没有独立IP地址

Docker使用了Linux的Namespace技术来进行资源隔离,如PID Namespace(隔离进程)、Mount Namespace(隔离文件系统)、Network Namespace(隔离网路)等。一个Network Namespace提供了一份独立的网路环境,包括网卡、路由、iptables规则等,均与其他Network Namespace隔离。一个docker容器一般会分配一个独立的Network Namespace。

但是如果启动容器时使用host模式,那么此容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口范围。此时容器不再拥有隔离的、独立的网络栈,不拥有端口资源。

3.2、container模式

这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。

新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。

[root@aliyun ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
823ae713d67b nginx "/docker-entrypoint.…" 4 hours ago Up 4 hours 0.0.0.0:8088->80/tcp nginx02
2ddb5c52db61 nginx "/docker-entrypoint.…" 4 hours ago Up 4 hours 0.0.0.0:49157->80/tcp nginx01
#查看容器进程PID
[root@aliyun ~]# docker inspect -f '{{.State.Pid}}' 2ddb5c52db61
19528
#查看容器的进程、网络、文件系统等命名空间编号
[root@aliyun ~]# ls -l /proc/19528/ns
总用量 0
lrwxrwxrwx 1 root root 0 4月 20 14:07 ipc -> ipc:[4026532160]
lrwxrwxrwx 1 root root 0 4月 20 14:07 mnt -> mnt:[4026532157]
lrwxrwxrwx 1 root root 0 4月 20 10:34 net -> net:[4026532163]
lrwxrwxrwx 1 root root 0 4月 20 10:35 pid -> pid:[4026532161]
lrwxrwxrwx 1 root root 0 4月 20 14:07 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 4月 20 14:07 uts -> uts:[4026532
#新建一个容器,使用container模式
[root@aliyun ~]# docker run -itd --name nginx03 --net=container:2ddb5c52db61 nginx /bin/bash
69ef00e830ecf1da5eb1862b65edf1def73de6f399548d41339d650ec68cc07c
[root@aliyun ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
69ef00e830ec nginx "/docker-entrypoint.…" 5 seconds ago Up 4 seconds nginx03
823ae713d67b nginx "/docker-entrypoint.…" 4 hours ago Up 4 hours 0.0.0.0:8088->80/tcp nginx02
2ddb5c52db61 nginx "/docker-entrypoint.…" 4 hours ago Up 4 hours 0.0.0.0:49157->80/tcp nginx01
#查看nginx03的进程PID
[root@aliyun ~]# docker inspect -f '{{.State.Pid}}' 69ef00e830ec
27950
[root@aliyun ~]# ls -l /proc/27950/ns
总用量 0
lrwxrwxrwx 1 root root 0 4月 20 14:12 ipc -> ipc:[4026532284]
lrwxrwxrwx 1 root root 0 4月 20 14:12 mnt -> mnt:[4026532282]
lrwxrwxrwx 1 root root 0 4月 20 14:11 net -> net:[4026532163]
lrwxrwxrwx 1 root root 0 4月 20 14:12 pid -> pid:[4026532285]
lrwxrwxrwx 1 root root 0 4月 20 14:12 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 4月 20 14:12 uts -> uts:[4026532283]

3.3、none模式

使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为docker容器进行任何网络配置

也就是说,这个docker容器没有网卡、IP、路由等信息。这个网络模式下容器只有lo回环网络,没有其他网卡。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。

3.4、bridge模式

bridge模式是docker的默认网络模式

相当于VMware中的nat模式,容器使用独立Network Namespace,并连接到docker0虚拟网卡。通过docker0网桥以及iptables NAT表配置与宿主机通信,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。

  1. 当docker进程启动时,会在主机上创建一个docker0的虚拟网桥,此主机上启动的docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
  2. 从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备。
  3. Docker将veth pair设备的一段放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以veth*这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。
  4. 使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可使用iptables -t nat -nL查看。
posted on   雷子锅  阅读(156)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
 
点击右上角即可分享
微信分享提示