Docker容器如何通过DHCP,实现自动获取宿主机局域网IP

思路

  • Docker使用MacVLAN建立一个network
  • 容器中使用udhcpc自动获取IP
  • 宿主机配置MacVLAN Link来访问容器IP

Docker建立MacVLAN network

networks:
  lan:
    driver: macvlan
    driver_opts:
      parent: enp2s0

services:
  service_A:
    cap_add:
      - NET_ADMIN
    mac_address: "02:42:dd:cc:bb:aa"
    networks:
      - lan

这里使用docker-compose,先建立一个macvlan驱动的network,并且不配置subnetgateway
之所以这样做,是因为如果配置了外面局域网的网段,Docker会自动分配一个IP给容器,而这个IP很可能在外部局域网里已经存在了,且这个IP不被局域网路由器所管理。

以当前配置将容器启动之后,Docker会自动给lan network一个网段,自动给容器分配一个IP(和外部局域网网段不同)。

容器中使用udhcpc自动获取IP

在上一步容器启动之后,我们可以尝试进入运行中容器,看看是否有udhcpc命令,并且尝试通过DHCP获取局域网IP。

docker exec -it service_A bash

udhcpc

如果一切顺利,应该会看到类似下面的输出,说明就是成功从局域网DHCP获取到IP,并且这个IP可以通过路由器进行管理。
如果出现permission相关报错,可能是容器缺少NET_ADMIN权限。

udhcpc: started, v1.37.0
udhcpc: broadcasting discover
udhcpc: broadcasting select for 192.168.2.173, server 192.168.2.1
udhcpc: lease of 192.168.2.173 obtained from 192.168.2.1, lease time 43200

尝试成功之后,我们可以修改docker-compose.ymlserviceendpoint字段,让容器在启动时自动运行udhcpc来获取IP。
并且推荐在路由器上将这个IP设置为静态IP,和容器MAC绑定,方便我们下面做宿主机的MacVLAN Link。

宿主机添加MacVLAN Link

完成上面一步之后,我们会发现在局域网的其他设备可以通过容器IP访问容器的服务,但是在宿主机上不能通过容器IP访问容器。
这里我们需要配置MacVLAN Link来解决这个问题。
打开/etc/systemd/network文件夹,添加以下两个文件:

30-macvlan0.netdev

[NetDev]
Name=macvlan0
Kind=macvlan

[MACVLAN]
Mode=bridge

30-macvlan0.network

[Match]
Name=macvlan0

[Route]
Destination=192.168.2.173
Gateway=192.168.2.1
Metric=200

这里要注意,在.network文件里,Destination只能为容器IP,不然可能路由表会出错。
并且配置合适的Metric路由跃点。

最后,修改已有的DHCP接口配置,可能是这样的:
20-wired.network

[Match]
Name=enp2s0

[Network]
DHCP=yes
MACVLAN=macvlan0

[DHCP]
RouteMetric=100

在其中Network部分添加MACVLAN字段。
最后重启systemd-networkd服务,宿主机应该就可以访问容器IP了。
sudo systemctl restart systemd-networkd

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据