思路
- 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,并且不配置subnet
和gateway
。
之所以这样做,是因为如果配置了外面局域网的网段,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.yml
里service
的endpoint
字段,让容器在启动时自动运行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