官方有关于网桥和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

root@ubuntu-docker:~# cat /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
 
# The loopback network interface
auto lo
iface lo inet loopback
 
# The primary network interface
#auto eth0
#iface eth0 inet dhcp
#
auto br0
iface br0 inet static
    address 192.168.5.116
    netmask 255.255.255.0
    gateway 192.168.5.1
    bridge_ports eth0
    bridge_stp off
    dns-nameservers 192.168.1.12 192.168.1.13
root@ubuntu-docker:~#

配置保存退出后,重启网络

root@ubuntu-docker:~# ifdown -a && ifup -a

配置完成后用ifconfig可以看到br0和eth0的状态信息如下(宿主机的ip地址为192.168.5.116):

br0       Link encap:Ethernet  HWaddr 00:0c:29:dc:47:11
          inet addr:192.168.5.116  Bcast:192.168.5.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fedc:4711/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:737 errors:0 dropped:0 overruns:0 frame:0
          TX packets:226 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:70000 (70.0 KB)  TX bytes:26394 (26.3 KB)
 
eth0      Link encap:Ethernet  HWaddr 00:0c:29:dc:47:11
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:70065 errors:0 dropped:151 overruns:0 frame:0
          TX packets:19621 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:23933126 (23.9 MB)  TX bytes:2321651 (2.3 MB)

2、网桥配置好后,剩下的就是docker相关的网络配置了。
a)容器启动的网络模式必须为none,用–net=none指定,比如

docker run -it --rm --net=none eeed74b237f9 /bin/bash

b)获取目标容器的id,我的是dfe83012cda2

root@ubuntu-docker:~# 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
root@ubuntu-docker:~#

c)配置ip的步骤有点繁琐,我写了个脚本。然后给脚本传递相关的参数就可以设置ip了。比如为容器dfe83012cda2设置静态ip地址192.168.5.123,掩码255.255.255.0,网关192.168.5.1。有个问题就是当容器重启后,设定的ip会丢失,此时需要重新执行该脚本一次。

root@ubuntu-docker:~# sh manual_con_static_ip.sh dfe83012cda2 192.168.5.123 24 192.168.5.1

脚本的内容如下(参考官方文档编写)

#/bin/bash
if [ -z $1 ] || [ -z $2 ] || [ -z $3 ] || [ -z $4 ];
then
        echo "*****Input the necessary parameters: CONTAINERID IP MASK GATEWAY"
        echo "*****Call the script like: sh manual_con_static_ip.sh  b0e18b6a4432 192.168.5.123 24 192.168.5.1"
        exit
fi
 
CONTAINERID=$1
SETIP=$2
SETMASK=$3
GATEWAY=$4
 
pid=`docker inspect -f '{{.State.Pid}}' $CONTAINERID`
mkdir -p /var/run/netns
find -L /var/run/netns -type l -delete
ln -s /proc/$pid/ns/net /var/run/netns/$pid
ip link add A type veth peer name B
brctl addif br0 A
ip link set A up
ip link set B netns $pid
ip netns exec $pid ip link set dev B name eth0
ip netns exec $pid ip link set eth0 up
ip netns exec $pid ip addr add $SETIP/$SETMASK dev eth0
ip netns exec $pid ip route add default via $GATEWAY

脚本包含的信息量较大,下面分行解有关语句的作用:

pid=`docker inspect -f '{{.State.Pid}}' $CONTAINERID`

为了操作容器需要获取容器的进程号PID,docker inspect 可以查看容器的底层信息,查看容器dfe83012cda2所有的底层相关信息,用docker inspect dfe83012cda2就可以查看。-f参数可以格式化输出给定的信息,比如查看容器的状态

root@ubuntu-docker:~# docker inspect -f '{{.State.Running}}' dfe83012cda2
true
root@ubuntu-docker:~#

为容器创建net命名空间,建立点对点连接(容器命名空间网卡和宿主上生成的网卡点对点),确保存放net命名空间的目录/var/run/netns存在,然后删除该目录失效的链接,再将容器的net命名空间文件软链接到/var/run/netns,以便执行ip netns能够读取。

mkdir -p /var/run/netns
find -L /var/run/netns -type l -delete
ln -s /proc/$pid/ns/net /var/run/netns/$pid

在宿主上创建2张直连网卡(A与B直连),将B作为容器里的网卡,A作为宿主机的网卡。

ip link add A type veth peer name B

将网卡A桥接到br0上,并启动网卡A

brctl addif br0 A
ip link set A up

将网卡B加入到相应的容器net命名空间,当网卡B加入到容器的net命名空间后,宿主机将无法查看到该网卡信息(执行ip netns时默认读取的目录是/var/run/netns)

ip link set B netns $pid

ip netns exec能进入容器的net命名空间,可以用来配置容器net命名空间的网络参数,配置容器内的网卡B

ip netns exec $pid ip link set dev B name eth0
ip netns exec $pid ip link set eth0 up
ip netns exec $pid ip addr add $SETIP/$SETMASK dev eth0
ip netns exec $pid ip route add default via $GATEWAY

接下来先了解下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的命名会造成冲突,不过解决还是很简单的,嘿嘿。
后来把脚本优化了下,可能使用起来更合理:

#/bin/bash
if [ -z $1 ] || [ -z $2 ] || [ -z $3 ] || [ -z $4 ] || [ -z $5 ];
then
        echo "*****Input the necessary parameters: CONTAINERID IP MASK GATEWAY ETHNAME"
        echo "*****Call the script like: sh manual_con_static_ip.sh  b0e18b6a4432 192.168.5.123 24 192.168.5.1 deth0"
        exit
fi
  
CONTAINERID=$1
SETIP=$2
SETMASK=$3
GATEWAY=$4
ETHNAME=$5
 
#判断宿主机网卡是否存在
ifconfig $ETHNAME > /dev/null 2>&1
if [ $? -eq 0 ]; then
    read -p "$ETHNAME exist,do you want delelte it? y/n " del
    if [[ $del == 'y' ]]; then
    ip link del $ETHNAME
    else
    exit
    fi
fi
#
pid=`docker inspect -f '{{.State.Pid}}' $CONTAINERID`
mkdir -p /var/run/netns
find -L /var/run/netns -type l -delete
 
if [ -f /var/run/netns/$pid ]; then
    rm -f /var/run/netns/$pid
fi
ln -s /proc/$pid/ns/net /var/run/netns/$pid
#
ip link add $ETHNAME type veth peer name B
brctl addif br3 $ETHNAME
ip link set $ETHNAME up
ip link set B netns $pid
#先删除容器内已存在的eth0
ip netns exec $pid ip link del eth0 > /dev/null 2>&1
#设置容器新的网卡eth0
ip netns exec $pid ip link set dev B name eth0
ip netns exec $pid ip link set eth0 up
ip netns exec $pid ip addr add $SETIP/$SETMASK dev eth0
ip netns exec $pid ip route add default via $GATEWAY

文章出处:http://www.xiaomastack.com/2015/02/06/docker-static-ip/

6 Comments

Add your comment

    1.  

      小马哥,我使用您的脚步配置了容器内的网络后容器内部已经能看到配置的ip网关子网掩码了可以ping 通宿主和容器自己的ip。但是ping其他物理机的ip还是ping不通

      •  

        开启内核net forward,网关设置为宿主机地址,宿主机本身要和其他物理主机打通,应该就没有问题了。

FW Docker为容器分配指定物理网段的静态IP的更多相关文章

  1. (转帖) 为Docker容器指定自定义网段的固定IP/静态IP地址

    作者:雨水,日期:2016-04-09  CSDN博客: http://blog.csdn.net/gobitan 摘要:Docker容器运行的时候默认会自动分配一个默认网桥所在网段的IP地址.但很多 ...

  2. docker 创建容器时指定容器ip

    Docker创建容器时默认采用bridge网络,自行分配ip,不允许自己指定. 在实际部署中,我们需要指定容器ip,不允许其自行分配ip,尤其是搭建集群时,固定ip是必须的. 我们可以创建自己的bri ...

  3. 为Docker容器指定自定义网段的固定IP/静态IP地址

    第一步:创建自定义网络 备注:这里选取了172.172.0.0网段,也可以指定其他任意空闲的网段 docker network create --subnet=172.172.0.0/16 docke ...

  4. docker 运行容器时指定--sysctl参数来设置系统参数

    指定--sysctl参数来设置系统参数,通过这些参数来调整系统性能,Docker通过一个 ValidateSysctl函数来限制 sysctl参数可以传入的项,源码如下: // docker/opts ...

  5. Docker 添加容器SSH服务

    很多时候我们需要登陆到容器内部操作,此时我们就需要开启容器的SSH支持了,下面的小例子将具体介绍三种分配IP地址的方法,分别是pipworl分配,commit分配,Docker分配等. 基于commi ...

  6. 为Docker容器设置静态IP

    此文已由作者袁欢授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 创建docker容器 docker run -it --name=yh -h yh --net=none de ...

  7. docker容器分配静态IP

    最近因为工作要求需要用学习使用docker,最后卡在了网络配置这一块.默认情况下启动容器的时候,docker容器使用的是bridge策略比如: docker run -ti ubuntu:latest ...

  8. docker 现实---联网多台物理主机,容器桥到物理网络(三)

    docker 默认桥接卡docker0 只有当这个单元中的所有容器桥接卡.例如,在主机虚拟网络适配器容器看通常称为veth***  和docker只要把这些卡桥接在一起,例如下面的附图: waterm ...

  9. docker应用-5(使用overlay 网络进行容器间跨物理主机通信)

    同一个主机上的Docker容器之间通信 docker 引擎会在主机上增加一个docker0网卡,该网卡具有双重身份: 1.从容器视角,网桥(交换机)身份docker0 对于运行在同一个主机上的各个容器 ...

随机推荐

  1. node基础 --工具

    npm  //Node.js Package Manager 查询版本号:npm --version/npm version 查询模块:npm search <name> 查看模块相关信息 ...

  2. html表单应用

    <!DOCTYPE html> <html> <head> <meta name="generator" content="HT ...

  3. [Unity3D]脚本中Start()和Awake()的区别

    Unity3D初学者经常把Awake和Start混淆. 简单说明一下,Awake在MonoBehavior创建后就立刻调用,Start将在MonoBehavior创建后在该帧Update之前,在该Mo ...

  4. jQuery回调、递延对象总结(一)jQuery.Callbacks详解

    前言: 作为参数传递给另一个函数执行的函数我们称为回调函数,那么该回调又是否是异步的呢,何谓异步,如:作为事件处理器,或作为参数传递给 (setTimeout,setInterval)这样的异步函数, ...

  5. Java集合的线程安全用法

    线程安全的集合包含2个问题 1.多线程并发修改一 个 集合 怎么办? 2.如果迭代的过程中 集合 被修改了怎么办? a.一个线程在迭代,另一个线程在修改 b.在同一个线程内用同一个迭代器对象进行迭代. ...

  6. c# 使用GetOleDbSchemaTable获取access数据库结构

    c# 使用GetOleDbSchemaTable获取access数据库结构 ado.net可以使用GetOleDbSchemaTable方法来获取access数据库的结构,但得到的datatable的 ...

  7. c++模版函数

    1.定义 可以使用class或者typename字段来申明 template <class T> template <class T1, class T2, ...class TN& ...

  8. OpenCV 2.4.11 VS2012 Configuration

    Add in the system Path: C:\opencv\build\x86\vc11\bin; Project->Project Property->Configuration ...

  9. imread() not working in OpenCV 2.4.11 Debug mode

    The OpenCV function imread() not working in OpenCV 2.4.11 Debug mode of VS2010 under Win32, the way ...

  10. 新鲜出炉的30个精美的 jQuery & CSS3 效果【附演示和教程】

    新鲜出炉的30个精美的 jQuery & CSS3 效果[附演示和教程]   作为最流行的 JavaScript 开发框架,jQuery 在现在的 Web 开发项目中扮演着重要角色,它简化了 ...