FW Docker为容器分配指定物理网段的静态IP

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

[email protected]:~# 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

[email protected]:~#

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

[email protected]:~# 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

[email protected]:~# 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

[email protected]:~#

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

[email protected]:~# 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参数可以格式化输出给定的信息,比如查看容器的状态

[email protected]:~# docker inspect -f ‘{{.State.Running}}‘ dfe83012cda2

true

[email protected]:~#

为容器创建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. Cenwen139 2015/08/26 at 19:51

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

      登录以回复

      • 小马 2015/08/27 at 09:43

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

时间: 2024-07-29 22:40:51

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

docker 创建容器时指定容器ip

Docker创建容器时默认采用bridge网络,自行分配ip,不允许自己指定. 在实际部署中,我们需要指定容器ip,不允许其自行分配ip,尤其是搭建集群时,固定ip是必须的. 我们可以创建自己的bridge网络 : mynet,创建容器的时候指定网络为mynet并指定ip即可. 查看网络模式 docker network ls 创建一个新的bridge网络 docker network create --driver bridge --subnet=172.18.12.0/16 --gatewa

centos7 docker宿主机配置桥接物理网络终极实战

1.停止docker daemon,并删除docker0 systemctl stop docker.service ip link set dev docker0 down brctl delbr docker0 2.创建桥接物理网络: 2.1.思路整理 (1)新建br0桥接网络,brctl show可以查看(需安装bridge-utils) (2)将宿主机物理网卡IP.掩码.网关.dns(或者dhcp)配置到br0上 (3)删除宿主机物理网卡IP.掩码.网关.dns(或者dhcp)配置 (4

为Docker容器设置静态IP

此文已由作者袁欢授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 创建docker容器 docker run -it --name=yh -h yh --net=none debian:sshd bash   ### 确保使用--net=none参数,此时新建的容器内不会创建网卡 docker ps 此时登录容器查看IP,会发现没有eth0网卡: [email protected]:/# ifconfig -alo        Link encap:Local Loop

docker容器设置静态IP与宿主机同一网段通信

很早以前弄过docker容器设置静态ip地址以及容器与容器之间通信,用的不多所以没有记录下来. 今天在网上看到个文章关于设置静态ip地址的.就自己实战下.对了还有个pipework也可以设置.. 操作系统环境 [email protected]:~# cat /etc/issue Ubuntu 14.04.3 LTS \n \l 宿主机(系统采用ubuntu-14.04.1-server-amd64)的网络采用桥接模式(默认是DHCP模式,还有一种模式就是静态IP),网桥的网段与物理网段相同.目

docker之docker容器flannel模式多网段跨主机通信

一.简介flannel是为实现多网段通信的第三方的解决方案, 是 CoreOS 开发的容器网络解决方案.flannel 为每个 host 分配一个 subnet,容器从此 subnet 中分配 IP,这些 IP 可以在 host 间路由,容器间无需 NAT 和 port mapping 就可以跨主机通信.每个 subnet 都是从一个更大的 IP 池中划分的,flannel 会在每个主机上运行一个叫 flanneld 的 agent,其职责就是从池子中分配 subnet.为了在各个主机间共享信息

docker容器分配静态IP

最近因为工作要求需要用学习使用docker,最后卡在了网络配置这一块.默认情况下启动容器的时候,docker容器使用的是bridge策略比如: docker run -ti ubuntu:latest /bin/bash 等效于 docker run -ti --net=bridge ubuntu:latest /bin/bash bridge策略下,docker容器自动为我们分配了一个IP地址,并连接到docker0的网桥上.但这里有一个问题,这个IP地址并不是静态分配的,这对我们的对容器的实

ASP.NET Core 如何在运行Docker容器时指定容器外部端口(docker compose)

原文:ASP.NET Core 如何在运行Docker容器时指定容器外部端口(docker compose) 前面我写了一系列关于持续集成的文章,最终构建出来的镜像运行之后,应该会发现每次构建运行之后端口都变了,这对于我们来说是十分不方便的,所以我们可以通过修改docker compose的配置文件来完成我们的需求. 熟悉Docker的都应该知道容器运行时其内部会有一个端口以映射到我们外部的端口,我们需要固定的就是这个外部端口. 打开 docker-compose.override.yml 文件

Docker基础-容器操作

1.创建容器 1.新建容器 可以使用docker create命令新建一个容器. [[email protected] ~]# docker create -it ubuntu:latest ffc9099be315f1b94876410c7d74dcd20e311e735e638080dd477534c063a6d6 [[email protected]-node1 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS

跟我一起学docker(四)--容器的基本操作

1.创建容器 Docker的容器十分轻量级,用户可以随时创建或删除容器. 新建容器:docker create Example:docker create –ti ubuntu 说明:使用docker create命令创建的容器处于停止状态,可以使用docker start命令启动它. 新增加了一个name等于test_create的,status等于create 新建并启动容器:docker run Example: docker run ubuntu/bin/echo "Hello Worl