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网络模式
- Host:容器不会虚拟出自己的网卡,配置主机的IP等,而是使用宿主机的IP和端口
- Container:创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围
- None:该模式关闭了容器的网络功能
- Bridge:默认为该模式,此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0的虚拟网桥,通过docker0网桥以及iptables nat表配置与宿主机通信
- 自定义网络
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容器连接到一个虚拟网桥上。
- 当docker进程启动时,会在主机上创建一个docker0的虚拟网桥,此主机上启动的docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
- 从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备。
- Docker将veth pair设备的一段放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以veth*这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。
- 使用
docker run -p
时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可使用iptables -t nat -nL
查看。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具