Docker 的 --network=none 模式啟動容器時不創建任何網絡接口(僅保留 lo 回環),但容器擁有獨立的 Network Namespace。這為完全自定義網絡拓撲(如手動創建 veth pair、配置路由、實現容器間直連)提供了乾淨的基礎環境。本文實戰演示從啟動 none 容器到手動構建雙容器互通的全過程。
$ docker run -it --rm --network=none centos:6.3 /bin/bash [root@container /]# ifconfig lo: flags=73mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10 loop txqueuelen 1000 (Local Loopback) RX packets 0 bytes 0 (0.0 B) TX packets 0 bytes 0 (0.0 B) # 無 eth0、無橋接、無 NAT,完全隔離
$ docker run -itd --name c1 --network=none centos:6.3 sleep 3600
$ docker run -itd --name c2 --network=none centos:6.3 sleep 3600
$ PID1=$(docker inspect -f '{{.State.Pid}}' c1) # 例:695
$ PID2=$(docker inspect -f '{{.State.Pid}}' c2) # 例:638
$ mkdir -p /var/run/netns $ ln -sf /proc/$PID1/ns/net /var/run/netns/$PID1 $ ln -sf /proc/$PID2/ns/net /var/run/netns/$PID2
# 創建一對虛擬網卡:A (給 c1)、B (給 c2) $ ip link add A type veth peer name B # 將 A 移入 c1 的網絡命名空間 $ ip link set A netns $PID1 # 將 B 移入 c2 的網絡命名空間 $ ip link set B netns $PID2
# c1 侧:10.1.1.1/32,下一跳指向 10.1.1.2 $ ip netns exec $PID1 ip addr add 10.1.1.1/32 dev A $ ip netns exec $PID1 ip link set A up $ ip netns exec $PID1 ip route add 10.1.1.2/32 dev A # c2 侧:10.1.1.2/32,下一跳指向 10.1.1.1 $ ip netns exec $PID2 ip addr add 10.1.1.2/32 dev B $ ip netns exec $PID2 ip link set B up $ ip netns exec $PID2 ip route add 10.1.1.1/32 dev B
$ docker exec c1 ping -c 4 10.1.1.2 PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data. 64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.084 ms 64 bytes from 10.1.1.2: icmp_seq=2 ttl=64 time=0.071 ms 64 bytes from 10.1.1.2: icmp_seq=3 ttl=64 time=0.073 ms 64 bytes from 10.1.1.2: icmp_seq=4 ttl=64 time=0.069 ms --- 10.1.1.2 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3505ms
| 技術點 | 說明 |
|---|---|
/32 掩碼 | 點對點鏈路無需廣播域,單個 IP 即構成子網,節省地址空間 |
路由 dev A 不指定 gateway | 直連鏈路,數據包直接從接口發送,由對端接收 |
| veth pair | 虛擬設備對,一端發送的數據包直接出現在另一端,像一根網線 |
| Network Namespace 隔離 | 容器進程僅見自己的網卡、路由表、iptables 規則 |
/var/run/netns 掛載點 | ip netns exec 要求命名空間文件在此目錄下 |
#!/bin/bash # create_p2p_net.sh# 例:./create_p2p_net.sh c1 c2 10.1.1.1 10.1.1.2 set -e C1=$1; C2=$2; IP1=$3; IP2=$4 PID1=$(docker inspect -f '{{.State.Pid}}' $C1) PID2=$(docker inspect -f '{{.State.Pid}}' $C2) mkdir -p /var/run/netns ln -sf /proc/$PID1/ns/net /var/run/netns/$PID1 ln -sf /proc/$PID2/ns/net /var/run/netns/$PID2 VETH1="veth_${C1}"; VETH2="veth_${C2}" ip link add $VETH1 type veth peer name $VETH2 ip link set $VETH1 netns $PID1 ip link set $VETH2 netns $PID2 ip netns exec $PID1 ip addr add $IP1/32 dev $VETH1 ip netns exec $PID1 ip link set $VETH1 up ip netns exec $PID1 ip route add $IP2/32 dev $VETH1 ip netns exec $PID2 ip addr add $IP2/32 dev $VETH2 ip netns exec $PID2 ip link set $VETH2 up ip netns exec $PID2 ip route add $IP1/32 dev $VETH2 echo "P2P network created: $C1($IP1) <--> $C2($IP2)"
# 刪除容器時自動清理 veth pair 和 netns 掛載點 $ docker rm -f c1 c2 # 手動清理殘留 $ rm -f /var/run/netns/695 /var/run/netns/638