Docker 学习笔记:网络篇

Docker 学习笔记:网络篇

本笔记承接容器资源限制部分,深入讲解 Docker 的原生网络模型,涵盖 none/host/bridge 三种网络、自定义网络、容器间通信(IP/DNS/joined 容器)以及容器与外部世界的双向访问。


13. Docker 网络概览

Docker 安装时会自动创建三个网络:

bash

复制代码
$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
a1b809382f0d   bridge    bridge    local
6ad21ed9eaf1   host      host      local
4e31521b27c6   none      null      local

14. none 和 host 网络

14.1 none 网络

none 网络意味着容器只有 lo 回环接口,完全封闭。

bash

复制代码
$ docker run -it --network=none busybox
/ # ifconfig
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0

适用场景:对安全性要求极高且无需网络的应用,例如只生成随机密码的离线程序。

14.2 host 网络

使用 --network=host 时,容器与宿主机共享同一个网络命名空间,网络配置完全一致。

bash

复制代码
$ docker run -it --network=host busybox
/ # ip a                  # 能看到宿主机所有网卡
/ # hostname
docker                   # 宿主机的主机名

优点 :性能最佳,无网络地址转换开销。
缺点 :端口冲突风险高,灵活性下降。
典型应用:需要直接配置宿主机网络的网络插件(如 Flannel)或以容器形式运行的监控代理。


15. bridge 网络(默认)

15.1 原理

Docker 在安装时创建一个名为 docker0 的 Linux bridge(相当于软件交换机),默认新建的容器都会连接到该网桥。

bash

复制代码
$ brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.02420be905a5       no

创建容器后,会自动生成一对 veth pair 虚拟网卡:一端在容器内(eth0),另一端挂在 docker0 上(如 vethddb2744)。

bash

复制代码
$ docker run -itd --name busybox1 busybox
$ brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.02420be905a5       no              vethddb2744

容器内查看:

bash

复制代码
$ docker exec -it busybox1 sh
/ # ip a
24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0

同时宿主机上会看到对应的另一端:

bash

复制代码
$ ip a | grep vethddb2744
25: vethddb2744@if24: ...

docker0 网桥的 IP 为 172.17.0.1/16,容器自动从该子网获取 IP。

15.2 查看 bridge 网络详情

bash

复制代码
$ docker network inspect bridge
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"

16. 自定义网络(用户定义 bridge)

与默认 bridge 相比,自定义网络提供 内置 DNS 解析,支持容器名称直接通信。

16.1 创建自定义 bridge 网络

bash

复制代码
# 自动分配子网
$ docker network create --driver bridge my_net

# 查看新建网桥
$ brctl show
bridge name     bridge id               STP enabled     interfaces
br-89f7bc11b602         8000.0242194d039e       no
docker0         8000.02420be905a5       no              vethddb2744

16.2 指定子网与网关

bash

复制代码
$ docker network create --driver bridge \
    --subnet 172.22.16.0/24 \
    --gateway 172.22.16.1 \
    my_net2

宿主机上会生成同名网桥 br-<ID> 并配置网关 IP:

bash

复制代码
$ ip a | grep br-ec761bc51778
27: br-ec761bc51778: <NO-CARRIER,...> mtu 1500 ...
    inet 172.22.16.1/24 brd 172.22.16.255 scope global br-ec761bc51778

16.3 使用自定义网络并指定静态 IP

bash

复制代码
$ docker run -it --network=my_net2 --ip 172.22.16.8 --name busybox3 busybox
/ # ip a
30: eth0@if31: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
    inet 172.22.16.8/24 ...

注意 :只有创建网络时指定了 --subnet 才能使用 --ip 分配静态 IP。


17. 理解容器间的连通性

17.1 同一自定义网络内互通

bash

复制代码
$ docker exec -it busybox2 sh
/ # ping -c3 172.22.16.8          # 同一 my_net2 中的另一个容器
64 bytes from 172.22.16.8: seq=0 ttl=64 time=0.197 ms
/ # ping -c3 172.22.16.1          # 网关
64 bytes from 172.22.16.1: seq=0 ttl=64 time=0.149 ms

同一网络中的容器与网关之间均可通信。

17.2 不同网络之间的隔离

默认 bridge 网络与自定义 my_net2 网络属于不同的网桥,Docker 通过 iptables 规则 DOCKER-ISOLATION 阻止了它们之间的双向流量。

bash

复制代码
$ docker exec -it busybox2 sh
/ # ping -c3 172.17.0.2          # busybox1 的 IP
--- 172.17.0.2 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss

17.3 将容器接入多个网络

bash

复制代码
$ docker network connect my_net2 busybox1

此时 busybox1 会多出一块 eth1 网卡,获得 my_net2 的 IP,从而可以与 busybox2 通信。


18. 容器间通信的三种方式

18.1 通过 IP 通信

两个容器只要处于同一网络,即可直接通过 IP 互通。

18.2 通过 Docker DNS Server

仅限用户自定义网络 。容器可以用 --name 指定的名称直接相互访问。

bash

复制代码
$ docker run -it --network=my_net2 --name bbox1 busybox
$ docker run -it --network=my_net2 --name bbox2 busybox
$ docker exec -it bbox2 sh
/ # ping -c3 bbox1
PING bbox1 (172.22.16.2): 56 data bytes
64 bytes from 172.22.16.2: seq=0 ttl=64 time=0.177 ms

默认 bridge 网络 不支持 DNS 名称解析。

18.3 joined 容器(共享网络栈)

通过 --network=container:目标容器名 让新容器与目标容器共享同一个网络命名空间。

bash

复制代码
$ docker run -d --name web1 httpd
$ docker run -it --network=container:web1 busybox
/ # ip a              # 与 web1 的 IP 和 MAC 完全相同
/ # wget 127.0.0.1    # 直接通过 localhost 访问 web1 的服务

适用场景:需要高效 loopback 通信,或监控其他容器的网络流量。


19. 容器访问外部世界

19.1 默认行为

容器无需额外配置即可访问外网(如 ping www.baidu.com),这是通过 NAT(网络地址转换) 实现的。

19.2 NAT 原理解析

在宿主机 iptables 的 NAT 表中存在类似规则:

text

复制代码
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

当容器向外发包时,数据包经过 docker0 网桥,匹配该规则后被 MASQUERADE,即将 源 IP 替换为宿主机外网接口的 IP,从而能够访问外网并接收回复。

可以用 tcpdump 抓包观察:

bash

复制代码
# 在宿主机两个窗口分别抓包
$ tcpdump -i docker0 -n icmp
$ tcpdump -i ens160 -n icmp

# 容器中 ping 外网
$ docker run -it busybox ping www.baidu.com
  • docker0 上看到的源 IP 是容器 IP(如 172.17.0.2
  • ens160 上看到的源 IP 已经被替换为宿主机 IP(如 192.168.108.30

20. 外部世界访问容器

通过 端口映射 让外部流量到达容器内部服务。

20.1 动态端口映射

bash

复制代码
$ docker run -d -p 80 httpd
$ docker port <容器ID>
80/tcp -> 0.0.0.0:32768

访问 http://<宿主机IP>:32768 即可访问容器内的 HTTP 服务。

20.2 指定固定端口

bash

复制代码
$ docker run -d -p 8080:80 httpd
$ curl http://192.168.108.30:8080
<html><body><h1>It works!</h1></body></html>

每个映射的端口,宿主机都会启动一个 docker-proxy 进程负责将流量转发到容器。

bash

复制代码
$ ps aux | grep docker-proxy

原理流程(以 0.0.0.0:8080->80/tcp 为例)

  1. docker-proxy 监听宿主机 8080 端口。
  2. 外部请求到达宿主机 8080 端口。
  3. docker-proxy 将请求转发到容器的 IP 和 80 端口。
  4. 容器处理请求并原路返回。

21. 知识点速查表

21.1 Docker 原生网络模式对比

网络模式 配置方式 网络隔离 性能 典型场景
none --network=none 完全无网络(仅 lo) 不适用 离线安全任务
host --network=host 无(共享宿主机网络栈) 最高 高性能网络、网络插件
bridge 默认 独立网络命名空间,通过 NAT 访问外网 较好 一般容器应用
自定义 bridge --network=my_net 同 bridge,但内建 DNS 需要名称解析的多容器应用

21.2 容器间通信方式速查

方式 适用网络 关键命令/配置
IP 直连 任意同一网络 ping <容器IP>
内置 DNS 仅用户自定义网络 --name 名称,直接 ping 容器名
joined 容器 所有网络 --network=container:<目标容器>,共享网络栈

21.3 容器与外部通信速查

方向 实现技术 关键命令
容器 → 外部 NAT (MASQUERADE) 无需配置,自动生效
外部 → 容器 端口映射 + docker-proxy -p 宿主机端口:容器端口

21.4 常用网络管理命令

命令 功能
docker network ls 列出所有网络
docker network inspect <网络名> 查看网络详细信息(子网、网关、容器等)
docker network create --driver bridge <网络名> 创建自定义网络
docker network connect <网络名> <容器名> 将容器接入指定网络
docker network disconnect <网络名> <容器名> 将容器从网络断开
docker port <容器名> 查看容器端口映射情况
brctl show 查看宿主机 Linux bridge 信息(需安装 bridge-utils)

本笔记至此覆盖 Docker 网络的单机场景,后续将进入存储卷与日志监控部分。

相关推荐
cui_ruicheng1 小时前
Linux线程(四):线程池、日志系统与单例模式
linux·开发语言·单例模式
24白菜头1 小时前
MySQL学习笔记
数据库·笔记·学习·mysql
Bat U1 小时前
JavaEE|网络编程
运维·服务器·网络
gs801401 小时前
避坑指南:Nginx 多层代理下的“404”与“重定向死循环”深度排查
运维·nginx
剑锋所指,所向披靡!1 小时前
计算机网络的数据链路层
网络·计算机网络
被放养的研究生1 小时前
Windows 与 Linux 文件系统区别及常见对应关系
linux·运维·windows
问心无愧05131 小时前
ctf show web入门54
前端·笔记
小陈phd1 小时前
多模态大模型学习笔记(三十九)——生成式与Transformer式OCR:从“像素抄录“到“文档智能“的完整演进
笔记·学习·transformer
眷蓝天1 小时前
Kubernetes 特殊容器技术详解
云原生·容器·kubernetes