在软路由中玩转 Docker——openwrt 自定义网桥

2024-08-27 01:43:11 12点赞 72收藏 10评论

写在前面

前面一篇写了软路由的安装以及启用 docker 服务

本文主要介绍如何在 openwrt 上优化 docker 网络,文章大纲如下

在软路由中玩转 Docker——openwrt 自定义网桥

通过本文,你可以实现:

  • openwrt 的容器与路由器下的普通设备互联互通

  • openwrt 的容器访问路由器下的普通设备,如 nas 设备时,不需要经过 NAT 导致性能损耗

为什么不用 docker0?

openwrt 的 docker 网络使用的是默认的 docker0 bridge,会存在以下的缺陷:

  • 容器与其他设备不在同个子网,其他设备无法与 openwrt 容器进行直接通信

  • 容器访问外网需要经过 docker0 虚拟网卡来进行 NAT,存在一定性能损耗

  • 容器只能通过 DNAT 将需要暴露端口映射到宿主上,而宿主本身就是主路由,存在一定端口暴露风险

在软路由中玩转 Docker——openwrt 自定义网桥

具体分析见上图:

  • 台式机笔记本等,是无法直接访问 172.16.0.10 容器 A 的 IP

  • 容器 A 可以访问 NAS 10.0.0.2,但是数据包需要经过 docker0 网桥做一层 NAT 地址转换

虽说目前软路由性能也足够,但是有没更加优雅的方案?答案当然是有的

自定义网桥

macvlan 模式

之前在 unraid 上比较喜欢使用 br0 网络模式,本质上就是 macvlan,其有如下特性:

  • 容器的分配的 ip 与 unraid 宿主处于同个层次,也就是作为主路由的一个子网

  • 可以手动指定 ip 进行分配,也可自动递增分配

  • 可以直接获取到 ipv6

详细这部分详细的介绍可以看之前的文档:

所以一开始考虑也是 openwrt 上配置 macvlan,网上找到的教程也有配置成功的

在软路由中玩转 Docker——openwrt 自定义网桥

然而在实际配置中,macvlan 能够创建,但是与其他软路由下的设备就是无法互通

PS: 本文对应的方案我也回复到 issue 里面了,可以搜一下 “Openwrt 下 Docker 网络食用方法”

自定义网桥

在网上查资料折腾了许久仍无法解决,最后自己尝试通过自定义 bridge 模式来实现。

首先确定目前主路由 LAN 侧的网络情况:网络 - 接口

在软路由中玩转 Docker——openwrt 自定义网桥

从上图可以看到 LAN 侧信息:

  • 网卡名称:br-lan

  • 子网分配:10.0.0.0/24

然后 ssh 进入主路由来创建一个自定义的 bridge 网络(注意替换为自己的 LAN 网络)

docker network create -d bridge --subnet=10.0.0.0/24 --gateway=10.0.0.1 -o "com.docker.network.bridge.name"="br-lan" lanet

参数解释如下:

在软路由中玩转 Docker——openwrt 自定义网桥

执行之后,就可以在 openwrt 管理页面上看到

在软路由中玩转 Docker——openwrt 自定义网桥

接下来就可以正常创建一个新的容器,并使用该桥接网络看看效果

在软路由中玩转 Docker——openwrt 自定义网桥

这里我跑一个 nodered 容器:

  • 指定使用的网络为 lanet|bridge|10.0.0.0/24

  • 指定分配的 IP 地址为:10.0.0.50

其他的就按照正常创建 docker 的配置即可,之后启动容器

在软路由中玩转 Docker——openwrt 自定义网桥

可以看到容器能够正常启动并分配了我们指定的 IP

在软路由中玩转 Docker——openwrt 自定义网桥

进入控制台进行网络测试:

  • 可以看到容器只分配了一个 ipv4,无法像 unraid 的 macvlan 方案获取到 ipv6 地址

  • 同时还可以直接 ping 通我的 nas 地址,说明与接入主路由的其他设备是可以正常通信的

这样,我就可以直接在我的电脑上来访问这个 nodered 服务了

在软路由中玩转 Docker——openwrt 自定义网桥

并且因为没有暴露端口在宿主,也相对而言更加安全了,其网络模型变成了

在软路由中玩转 Docker——openwrt 自定义网桥

相当于从软路由 LAN 网络层面来看:

  • 每一个容器都是一个独立的设备,在网络层级上等同于台式机、笔记本、NAS 等

  • 因为容器与常规设备都处于同个子网,默认就可以互联互通

  • 同时也容器访问 NAS 也不需要经过一层 NAT 地址转换了,效率也更高了

写在后面

重启丢失网桥问题

上述操作因为没有固化,在路由器重启后,创建的自定义网桥也会被删除,需要重新创建

在软路由中玩转 Docker——openwrt 自定义网桥

这里可以通过将创建命令写入 /etc/rc.local 来实现开机自动创建自定义网桥

需要注意要将创建命令写在 exit 0 之前,否则不会被执行

IP 分配冲突问题

使用此方案,建议提前做好 IP 段分配的规划,以避免 IP 地址冲突。

以我的网络环境为例,目前存在 3 个需要分配 IP 的场景:

  • 路由器的 DHCP 服务,常规有线、无线设别接入主路由会走此方式分配 IP

  • unraid NAS 上使用 custom:br0 网络模式的容器,对应就是 macvlan

  • openwrt 上使用自定义网桥 lanet 的容器

对应的,我做了如下区分

在软路由中玩转 Docker——openwrt 自定义网桥

路由器 DHCP 部分,可在 网络 -> 接口 -> LAN -> DHCP服务器 上进行设置

在软路由中玩转 Docker——openwrt 自定义网桥

对于 unraid,因为我分配的 IP 就是 10.0.0.2 所以

  • unraid 上 custom:br0 模式的容器会从 10.0.0.3开始递增

  • 当然也可以手动在 unraid 上指定分配的 IP

此外,目前这种方式还存在一个缺陷,就是即使主路由有 ipv6 pd,openwrt 容器也是无法分配 ipv6

本文完,下一篇正式介绍旧路由的服务迁移,点赞关注不迷路在软路由中玩转 Docker——openwrt 自定义网桥

作者声明本文无利益相关,欢迎值友理性交流,和谐讨论~

展开 收起
10评论

  • 精彩
  • 最新
  • 作者创建的bridge和issue里创建的macvlan实际效果是一样的,对比了前后docker network inspect lanet,完全一致,实际都是bridge

    校验提示文案

    提交
    啊哈,我倒是没看那么细 [高兴]

    校验提示文案

    提交
    收起所有回复
  • 这种模式完美,不像docker0多一层转发,又解决了macvlan不能与宿主直接通信的问题,关键有些openwrt固件macvlan用不了。
    ip范围问题可以用--ip-range=10.0.0.1/26 自动分配前64个ip,与100-255完美分开,如果需要ipv6添加 --ipv6 --subnet=fd00::/64

    校验提示文案

    提交
    还没试过ipv6分配,理论上应该也可以,就是这个前缀要能动态匹配运营商分配的前缀,就是拿到公网v6了

    校验提示文案

    提交
    收起所有回复
  • docker是根容器,还是建议用podman来玩。

    校验提示文案

    提交
    [邪恶] 先放着,又不是不能用。

    校验提示文案

    提交
    只是说要有安全意识,国内玩家基本一窝蜂只知道docker,但并不知道docker属于根容器,一旦从容器内部攻破,那么的宿主机也很危险。但是国内玩家基本不会去考虑安全问题。如果使用了别有用心的一些镜像,大概率会直接接管你的宿主机。podman可以实现无根容器。

    校验提示文案

    提交
    还有1条回复
    收起所有回复
  • 赛博华佗!之前我用的都是LAN+bridge的,现在搞了个软路由死活不能给bridge通到wan上(而lan是通的)。用了博主这种办法能够优雅解决以上问题,并且不会和host抢端口!桥接lan太好了

    校验提示文案

    提交
    [高兴] 一开始我是想折腾macvlan来着,实在调不通

    校验提示文案

    提交
    收起所有回复
提示信息

取消
确认
评论举报

相关文章推荐

更多精彩文章
更多精彩文章
最新文章 热门文章
72
扫一下,分享更方便,购买更轻松