在Docker容器中更改默认路由

我有一个docker容器连接到两个networking,默认桥和一个自定义桥。 默认情况下,它仅在默认networking中链接到另一个容器,并通过自定义网桥,在本地networking中获取IP地址。

LAN -- [homenet] -- container1 -- [bridge] -- container2 sudo docker network inspect homenet [{ "Name": "homenet", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [{ "Subnet": "192.168.130.0/24", "Gateway": "192.168.130.8", "AuxiliaryAddresses": { "DefaultGatewayIPv4": "192.168.130.3" }}] }, "Internal": false, "Containers": { "$cid1": { "Name": "container", "EndpointID": "$eid1_1", "MacAddress": "$mac1_1", "IPv4Address": "192.168.130.38/24", } }, "Options": { "com.docker.network.bridge.name": "br-homenet" }, "Labels": {}}] 

和桥:

 sudo docker network inspect bridge [{ "Name": "bridge", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [{ "Subnet": "172.17.0.0/16" }] }, "Internal": false, "Containers": { "$cid2": { "Name": "container2", "EndpointID": "$eid2", "MacAddress": "$mac2", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" }, "$cid1": { "Name": "container1", "EndpointID": "$eid1_2", "MacAddress": "$mac1_2", "IPv4Address": "172.17.0.3/16", "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} }] 

这从内部networking工作得很好,但是,我有一个路由问题:

 sudo docker exec -it container1 route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0 172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0 192.168.130.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1 

我如何将默认路由更改为192.169.130.3,使其保持重新启动?

我可以在container1运行时更改它

  pid=$(sudo docker inspect -f '{{.State.Pid}}' container1) sudo mkdir -p /var/run/netns sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid sudo ip netns exec $pid ip route del default sudo ip netns exec $pid ip route add default via 192.168.130.3 

但重启后就没了。 我该如何改变呢?

更新:显然, networking的字典顺序也可能是问题的一部分。 当我有机会时,我会testing它。

如果我明白了这个问题,问题是: 当重新启动连接到多个网桥的容器时,如何select一个网桥用于默认路由?

我search了可用的选项,并进行了一些testing,我没有find任何docker命令行选项来指定默认路由,或者当容器连接到多个网桥时,默认网桥是默认网桥。 当我重新启动连接到默认网桥( bridge )和自定义网桥(您的homenet )的容器时,默认路由会自动设置为使用默认网桥(网关172.17.0.1 )。 这对应于你描述的行为。

解决scheme1:在运行命令中指定一个启动脚本,负责更改默认路由并启动容器必须运行的服务

 docker run \ --cap-add NET_ADMIN \ # to allow changing net settings inside the container --name container1 \ --restart always \ # restart policy your_image \ /path/to/your_start_script.sh 

your_start_script.sh

 ip route del default ip route add default via 192.168.130.3 # here goes instructions/services your container is supposed to run 

这个脚本必须在容器内部可用,它可以在共享文件夹( -v选项)上,或者在用Dockerfile构build的映像上加载。

注意:在将容器连接到自定义桥( your_start_script.sh docker network connect homenet container1 your_start_script.sh docker network connect homenet container1 )之前, your_start_script.sh将会崩溃,因为默认路由与任何可用networking都不对应。

我testingloggingcontainer1内的ip route的输出,运行时--restart always使用--restart always ,连接到自定义桥接后,它有所需的默认路由。

解决scheme2:在容器启动事件上设置来自主机的容器默认路由

 docker events --filter "container=container1" |\ awk '/container start/ { system("/path/to/route_setting.sh") }' 

其中route_setting.sh包含更改容器默认路由的说明:

 pid=$(sudo docker inspect -f '{{.State.Pid}}' container1) sudo mkdir -p /var/run/netns sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid sudo ip netns exec $pid ip route del default sudo ip netns exec $pid ip route add default via 192.168.130.3 

这个解决scheme避免了对容器赋予特殊的权限,并将路由改变的责任传递给主机。

与select的例子:

 dockerd --bip 10.1.0.1/24 

如果你使用Ubuntu 14.04 ,改变

 /etc/default/docker 

如果你使用Ubuntu 16.04 ,请更改

 /lib/systemd/system/docker