
Docker Container無疑是近10年來LINUX宇宙最偉大的“發明”之一,今天不懂Docker不能算入門了IT。Docker Container有好幾種網路方式,其中MACVLAN模式小U認爲是最好玩的,透過MACVLAN可以讓只有一個網卡的設備虛擬出多個“網口”,取得多個IP。但,只要玩過DOCKER MACVLAN的朋友都會發現一個問題:DOCKER MACVLAN NETWORK是不具備DHCP自動抓取IP的功能。本文分享兩個解決方法,又是一篇只有20分鐘寫的文章,請見諒。
摘要節點
Docker Container 的網路模式和他們的IP地址
Docker 容器有多種網路模式,每種模式都有其特定的用途和優點。以下是幾種常見的 Docker 網路模式簡單介紹:
1. Bridge 網路模式
Bridge 網路模式是 Docker 的預設網路模式。在這種模式下,Docker 會在宿主機上創建一個虛擬網橋(類似於軟體交換機),並將所有的容器連接到這個網橋上。每個容器都會被分配一個獨立的、宿主機內部虛擬內網的 IP 地址,並且這些容器之間可以通過內部 IP 地址進行通信。
2. Host 網路模式
在 Host 網路模式下,容器直接使用宿主機的網路堆棧,這意味著容器不會被分配獨立的網絡名稱空間。容器與宿主機共享相同的 IP 地址和網路接口。不會有單獨的IP地址。
3. Macvlan 網路模式
Macvlan 網路模式允許容器有自己的虛擬 MAC 地址,並且每個容器看起來像是一個獨立的、擁有獨立網口的物理設備,並獲得和宿主機同級的真實內網IP地址。這使得容器可以直接與宿主機網路上的其他設備通信,無需經過宿主機的網路堆棧。
4. Overlay 網路模式
Overlay 網路模式通常用於 Docker Swarm 或 Kubernetes 等集群環境中。這種模式允許在不同宿主機上的容器之間建立一個虛擬的 L2 網絡,使其可以跨主機通信。
Docker Macvlan 模式無法DHCP的問題
運行在Docker Macvlan 模式的容器,需要全手動的設定IP地址,無法DHCP。通常是怎麼做的?首先,先要根據宿主機所在的真實網域,創建一個相同的MACVLAN網路,例如最常見的家用路由器 192.168.1.1 的內網:
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 macvlan_net然後再手動指派 Docker Container 的IP地址,例如指定爲 192.168.1.100:
docker run -it --rm \
--network macvlan_net \
--ip 192.168.1.100 \
your_image這就相當於全靜態的IP配置。對於我們熟悉的人來說,問題不大,但是如果要把一個裝配了 DOCKER MACVLAN 容器的機器交給任意一戶人家、任意的路由器網路使用,那問題就大了。這種全靜態的IP配置,適應性是零,使用者必須符合以下全部要求,機器才能正常使用:
- 路由器的內網網域是 192.168.1.XXX
- 路由器的子網MASK 是 /24 或 255.255.255.0
- 192.168.1.100沒有被其他設備佔用
這顯然是不可能的。所以,小U以下提供兩種自適應的方法。
MACVLAN IP的解決方法方法一 (不完美)
方法一就是 Ups-Gemini 雙子VPN 1.0 系統採用的方法。這種方法是利用啓動script rc.local,自動抓取宿主機的IP信息(宿主機是能DHCP獲得IP地址的),然後反向分析出網域,再自我分配一個IP地址:
# rc.local
subnet=$(ip route | awk '/default/ {print $3}' | cut -d"." -f1-3)".0/24"
gateway=$(ip route | awk '/default/ {print $3}')
docker network create -d macvlan --subnet=$subnet --gateway=$gateway -o parent=eth0 mac_bridge
docker-compose -f /path/to/docker-compose.yaml up --force-recreate
# docker-compose.yaml
networks:
mac_bridge:
external: true聰明的你可以看出,這個邏輯有幾個潛在問題:
- 開機延遲內,宿主機必須要獲得IP地址。也就是說,如果開機時候沒有插網線,MACVLAN就建立不起來。
- 開機後宿主機更換路由器,網域更變了MACVLAN不會跟着變。必須重啓。
- IP網域的MASK必須是 /24 或 255.255.255.0。不過這點問題不大,我所接觸過的家用路由器產品,都是這個MASK,如果修改過的,都是高人,協助客製化修改並不困難。
- 如果偵測到的網域是 123.123.123.0/24,那麼指派MACVLAN的IP就是 123.123.123.2,相當數量的路由器的默認DHCP是從 2~254,這就需要客戶自行修改DHCP範圍。但有的客戶不知道DHCP是什麼,有的客戶的路由器沒有管理權限。這導致不時會出現IP衝突(雖然概率比較低)
MACVLAN IP DHCP完美解決方法
經過大約幾個月的摸索,小U發現可以利用另一種虛擬技術:Linux Container來解決這個問題。 Linux Container同樣具有和Docker相似的網路選項,但Linux Container的Macvlan是能夠自動抓取IP,而且MAC地址是persist不變的,也就說不僅僅能自動抓取到IP,而且DHCP得到的地址會相對穩定,這實在是太好用了!

小U接觸到Linux Container已經是發展過 LXC – LXD – INCUS 幾個階段,如果你也是新接觸,建議直接從INCUS開始。這兩篇文章是帶我入門的,是我找到最全面最清晰的教學(雖然有些舊,自己腦補更新):
使用 INCUS Linux Container的首先難點是安裝,他的安裝沒有Docker簡單,不過只要是Linux Kernel 和 Distribution 都支援,不要太舊,都難度不大。
INCUS Linux Container 的使用更偏向 Docker Compose,很多設定都有一個設定檔可以好像 nano / vi 去修改,不像 Docker,一旦啓動了,有些參數就不能改,要遷移到一個新的container。總體來說INCUS的設定更爲先進,更偏向與虛擬機的設定邏輯。
想比起Dockerhub 數之不盡的鏡像,INCUS Linux Container 的鏡像基本都是Linux的系統本身(出乎意料竟然有OpenWRT)。如果要使用 Docker鏡像,就要先INCUS出一個Debian/Ubuntu/Arch,然後在裡面裝Docker,那麼就完美把Docker MACVLAN 無法DHCP的問題完美解決了!
不過你就會問,這樣“套娃”多層虛擬,效能損耗厲害嗎?我用INCUS上面裝DEBIAN然後直接跑TAILSCALE並沒有覺得有損耗。但是,INCUS上面裝OPENWRT的損耗就厲害了,2.5GbE的網口速度連一半都不到(NAT)。這可能是之後還要研究的課題。
頂,又寫了40分鐘,收工啦!歡迎留言討論。

