当前位置:首页 > 技术 > 正文内容

深入解析容器网络:从 Linux 网络命名空间到 Docker 网络模式

访客 技术 2026年9月12日 11

理解容器网络离不开 Linux 内核提供的网络命名空间(network namespace)和虚拟以太网对(veth pair)等底层机制。本文将介绍如何手动创建和操纵网络命名空间,并通过 veth pair 实现隔离空间之间的通信,随后结合 Docker 的四种网络模式展开配置实例,并涉及端口映射、自定义网桥等常见操作。

Linux 网络命名空间的操作

网络命名空间允许不同进程拥有独立的网络栈,包括网卡、IP 地址、路由表、iptables 规则等。可以使用 ip netns 命令进行管理,该命令来自 iproute2 工具包,需要 root 权限。

创建命名空间

执行 ip netns add red 即可建立一个名为 red 的命名空间。可以通过 ip netns list 查看当前系统中的所有命名空间。

$ sudo ip netns add red
$ sudo ip netns add blue
$ sudo ip netns list
blue
red

在命名空间中执行命令

ip netns exec <namespace> <command> 可以在指定的命名空间中运行命令。例如查看 red 中的网络接口:

$ sudo ip netns exec red ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

默认只有回环接口 lo,且处于 DOWN 状态。可以将其启用:

$ sudo ip netns exec red ip link set lo up
$ sudo ip netns exec red ping -c 2 127.0.0.1

使用 veth pair 连接命名空间

不同命名空间之间默认无法直接通信,而 veth pair 就是实现连通性的关键。veth 设备总是成对出现,从一个端点发出的数据包会直接从另一个端点收到,就像一个网线连接了两个网卡。

veth pair 示意

创建 veth pair 并分配到命名空间

$ sudo ip link add veth-red type veth peer name veth-blue
$ sudo ip link set veth-red netns red
$ sudo ip link set veth-blue netns blue

这样,veth-red 属于 red 命名空间,veth-blue 属于 blue 命名空间。

配置 IP 地址并激活接口

$ sudo ip netns exec red ip addr add 192.168.10.1/24 dev veth-red
$ sudo ip netns exec red ip link set veth-red up
$ sudo ip netns exec blue ip addr add 192.168.10.2/24 dev veth-blue
$ sudo ip netns exec blue ip link set veth-blue up

验证连通性

$ sudo ip netns exec red ping 192.168.10.2
PING 192.168.10.2 (192.168.10.2) 56(84) bytes of data.
64 bytes from 192.168.10.2: icmp_seq=1 ttl=64 time=0.060 ms

还可对接口重命名,例如将 red 中的 veth-red 改为更易理解的名称:

$ sudo ip netns exec red ip link set veth-red down
$ sudo ip netns exec red ip link set dev veth-red name eth0
$ sudo ip netns exec red ip link set eth0 up

Docker 的四种网络模式

Docker 利用上述 Linux 底层技术提供了多种网络模式,下面演示每种模式的行为和适用场景。

Bridge 模式(默认)

在不指定 --network 时,容器会连接到 docker0 网桥。每个容器获得一个私有 IP,NAT 负责与外部通信。

$ docker run -it --rm --name c1 busybox
/ # ip addr show eth0
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0

显式指定 --network bridge 效果一致。

None 模式

使用 --network none 创建的容器只有 lo 接口,完全网络隔离。

$ docker run -it --rm --network none busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue
    inet 127.0.0.1/8 scope host lo

Container 模式

通过 --network container:<target> 可以让新容器共享另一个容器的网络命名空间,相当于两个进程共用同一套网络接口和 IP 地址。

先启动一个容器:

$ docker run -d --name web1 nginx

再启动另一个共享其网络的容器:

$ docker run -it --rm --network container:web1 busybox
/ # ip addr show eth0
...
    inet 172.17.0.2/16 ...

这样,两个容器直接通过相同的 localhost 通信,文件系统仍保持隔离。

Host 模式

--network host 会使容器直接使用宿主机的网络栈,容器内的网络接口与宿主机完全一致,适合对网络性能要求苛刻的场景。

$ docker run -it --rm --network host busybox
/ # ip addr show
1: lo: ...
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
    inet 192.168.32.125/24 ...

容器网络常用操作

定制主机名与 DNS

启动时通过 --hostname 注入主机名,--dns 指定 DNS 服务器:

$ docker run -it --rm --hostname mybox --dns 8.8.8.8 busybox
/ # hostname
mybox
/ # cat /etc/resolv.conf
nameserver 8.8.8.8

使用 --add-host 可向 /etc/hosts 中添加固定映射:

$ docker run -it --rm --add-host svc.example:10.0.0.50 busybox
/ # cat /etc/hosts
...
10.0.0.50       svc.example

端口映射

-p 选项用于将容器内端口发布到宿主机上,支持多种格式:

  • -p 80:随机主机端口映射到容器的 80 端口
  • -p 8080:80:主机 8080 映射到容器 80
  • -p 192.168.1.100:8080:80:指定主机 IP 和端口

查看映射结果:

$ docker run -d --name webapp -p 8080:80 nginx
$ docker port webapp
80/tcp -> 0.0.0.0:8080
$ curl http://localhost:8080

相应的 iptables 规则会随容器创建自动添加,并在容器停止后自动清理。

自定义网桥

除默认的 docker0 外,可以创建更多网桥来隔离网络平面。

$ docker network create --driver bridge --subnet 10.5.0.0/16 --gateway 10.5.0.1 mynet
$ docker network ls
NETWORK ID     NAME        DRIVER    SCOPE
db...          mynet       bridge    local
...

启动容器时指定自定义网络:

$ docker run -it --rm --network mynet --name app1 busybox
/ # ip a
eth0@if...: <...> mtu 1500 qdisc noqueue
    inet 10.5.0.2/16 ...

如果一个容器需要连接多个网络,可以使用 docker network connect 动态加入,由此获得多个网络接口并实现跨网段通信。

$ docker network connect mynet app2

修改 docker0 默认网桥属性

通过编辑 /etc/docker/daemon.json 可以调整 docker0 的子网、mtu、网关等参数,例如:

{
  "bip": "192.168.99.1/24",
  "default-gateway": "192.168.99.1"
}

保存后需重启 Docker 服务:sudo systemctl restart docker。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。