官方有关于网桥和IP配置的文档地址:https://docs.docker.com/articles/networking/
1、宿主机(系统采用ubuntu-14.04.1-server-amd64)的网络采用桥接模式(默认是DHCP模式,还有一种模式就是静态IP),网桥的网段与物理网段相同。目前的物理网段为192.168.5.1/24,网关是192.168.1.1,物理网卡设备为eth0
编辑配置文件/etc/network/interfaces,自定义网桥br0
1 | $ cat /etc/network/interfaces |
配置保存退出后,重启网络1
$ ifdown -a && ifup -a
配置完成后用ifconfig可以看到br0和eth0的状态信息如下(宿主机的ip地址为192.168.5.116):
1 | br0 Link encap:Ethernet HWaddr 00:0c:29:dc:47:11 |
2、网桥配置好后,剩下的就是docker相关的网络配置了。
a)容器启动的网络模式必须为none,用–net=none指定,比如
1 | docker run -it --rm --net=none eeed74b237f9 /bin/bash |
b)获取目标容器的id,我的是dfe83012cda21
2
3
4$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dfe83012cda2 centos:centos6.6 /bin/bash About an hour ago Up 23 minutes test
$
c)配置ip的步骤有点繁琐,我写了个脚本。然后给脚本传递相关的参数就可以设置ip了。比如为容器dfe83012cda2设置静态ip地址192.168.5.123,掩码255.255.255.0,网关192.168.5.1。有个问题就是当容器重启后,设定的ip会丢失,此时需要重新执行该脚本一次。
1 | $ sh manual_con_static_ip.sh dfe83012cda2 192.168.5.123 24 192.168.5.1 |
脚本的内容如下(参考官方文档编写)
1 | #/bin/bash |
脚本包含的信息量较大,下面分行解有关语句的作用:
1 | pid=`docker inspect -f '{ {.State.Pid}}' $CONTAINERID` |
为了操作容器需要获取容器的进程号PID,docker inspect 可以查看容器的底层信息,查看容器dfe83012cda2所有的底层相关信息,用docker inspect dfe83012cda2就可以查看。-f参数可以格式化输出给定的信息,比如查看容器的状态
1 | $ docker inspect -f '{ {.State.Running}}' dfe83012cda2 |
为容器创建net命名空间,建立点对点连接(容器命名空间网卡和宿主上生成的网卡点对点),确保存放net命名空间的目录/var/run/netns存在,然后删除该目录失效的链接,再将容器的net命名空间文件软链接到/var/run/netns,以便执行ip netns能够读取。
1 | mkdir -p /var/run/netns |
在宿主上创建2张直连网卡(A与B直连),将B作为容器里的网卡,A作为宿主机的网卡。
1 | ip link add A type veth peer name B |
将网卡A桥接到br0上,并启动网卡A
1 | brctl addif br0 A ip link set A up |
将网卡B加入到相应的容器net命名空间,当网卡B加入到容器的net命名空间后,宿主机将无法查看到该网卡信息(执行ip netns时默认读取的目录是/var/run/netns)
1 | ip link set B netns $pid |
ip netns exec能进入容器的net命名空间,可以用来配置容器net命名空间的网络参数,配置容器内的网卡B
1 | ip netns exec $pid ip link set dev B name eth0 |
接下来先了解下docker为容器创建网络的过程
《http://dockerpool.com/static/books/docker_practice/underly/network.html》
就会明白为什么要这么配置了。
1)创建一对虚拟接口,分别放到本地主机和新容器中;
2)本地主机一端桥接到默认的 docker0 或指定网桥上,并具有一个唯一的名字,如 veth65f9;
3)容器一端放到新容器中,并修改名字作为 eth0,这个接口只在容器的名字空间可见;
4)从网桥可用地址段中获取一个空闲地址分配给容器的 eth0,并配置默认路由到桥接网卡 veth65f9。 当我们使用--net=none
参数启动容器后,docker不对容器进行网络配置。如果需要容器网络可用需要我们按照相同的步骤配置容器的网络。
脚本还有一个BUG,就是当有多个容器需要配置网卡的时候,脚本中的网卡A和网卡B的命名会造成冲突,不过解决还是很简单的,嘿嘿。
后来把脚本优化了下,可能使用起来更合理:
1 | #/bin/bash |