参考文章: http://www.tuicool.com/articles/v2yQ7bA
创建网桥(可以写成一个脚本):
1 2 3 4 5 |
br_name=docker brctl addbr $br_name ip addr add 192.168.33.2/24 dev $br_name ip link set $br_name up brctl addif $br_name eth0 |
创建容器
1 |
docker create --net none -i -t docker.io/blalor/centos /bin/bash |
稍微整理一下原作者的命令,写一个脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
#!/bin/bash cid=$1 #containerid ip=$2 #192.168.199.200/24 gateway=$3 #192.168.199.1 br_name=$4 #br1 eth=$5 #eth1 if [[ "$1" == "-h" || "$1" == "--help" ]]; then echo "sh $0 cid ip gateway brname eth";exit 1 fi pid=$(docker inspect -f '{{.State.Pid}}' $cid) if [[ "$pid" == "" ]]; then echo "container $cid is not exists";exit 2 fi if [[ $pid == 0 ]]; then echo "container $cid is not running" echo -n "starting $cid..."; docker start $cid if [[ $? != 0 ]];then echo "[ fail ]";exit 3 fi echo "[ OK ]" pid=$(docker inspect -f '{{.State.Pid}}' $cid) fi # set up netns netns_dir=/var/run/netns [ -d $netns_dir ] || mkdir -p /var/run/netns # garbage collect for f in $netns_dir/*;do _pid=$(basename $f) if [ "*" == "$f" ]; then break;fi if [ "$pid" == "$_pid" ]; then echo "network is allready yet";exit 4 fi if ! kill -0 $_pid 2>/dev/null;then ip netns delete $_pid fi done ln -s /proc/$pid/ns/net /var/run/netns/$pid # set up bridge ip link add q$pid type veth peer name r$pid brctl addif $br_name q$pid ip link set q$pid up # set up docker interface ip link set r$pid netns $pid ip netns exec $pid ip link set dev r$pid name $eth ip netns exec $pid ip link set $eth up ip netns exec $pid ip addr add $ip dev $eth ip netns exec $pid ip route add default via $gateway |
注: 最新版本的iproute (至少在iproute-3.10.0-54.el7.x86_64 中)支持 -n 选项,功能为:
1 2 3 4 5 6 7 8 |
-n, -netns <NETNS> switches ip to the specified network namespace NETNS. Actually it just simplifies executing of: ip netns exec NETNS ip [ OPTIONS ] OBJECT { COMMAND | help } to ip -n[etns] NETNS [ OPTIONS ] OBJECT { COMMAND | help } |
至少 iproute-3.10.0-21.el7.x86_64 中还没有该选项, 也就是说
1 |
ip netns exec 7819 ip addr show |
等价于
1 |
ip -n 7819 addr show |
如下br1是我做的网桥:
当docker容器stop时,这里的q7443也就消失了,但是网络名字空间中依然会存在; 可以通过 ip netns delete 来删除
一种情况,由于我的docker宿主机是virtualbox做的虚拟机,virtualbox虚拟机使用的桥接模式,所以,我这么做出来的docker虚拟机是访问不了外网的;因为,尽管docker虚拟机可以往docker宿主机的网卡上写数据,virtualbox的宿主机上的后台进程也不会发送该数据的(至少不会接受响应的数据)。
其实,有一个叫做pipework的工具可以很方便地给容器设置ip; 但是都没有提供卸载容器网卡的功能,有一种比较方便的办法: nsenter 进去 ifdown 就可以了