原
2016 年 09 月 29 日 17:42:37
首先讲一下 docker 的网络模式:
我们使用 docker run 创建容器时, 可以使用 --net 选项指定容器的网络模式, docker 一共有 4 中网络模式:
1:bridge 模式,--net=bridge(默认).
这是 dokcer 网络的默认设置. 安装完 docker, 系统会自动添加一个供 docker 使用的网桥 docker0, 我们创建一个新的容器时, 容器通过 DHCP 获取一个与 docker0 同网段的 IP 地址. 并默认连接到 docker0 网桥, 以此实现容器与宿主机的网络互通. 如下:
2:host 模式,--net=host.
这个模式下创建出来的容器, 将不拥有自己独立的 Network Namespace, 即没有独立的网络环境. 它使用宿主机的 ip 和端口.
3:container 模式,--net=container:NAME_or_ID.
这个模式就是指定一个已有的容器, 共享该容器的 IP 和端口. 除了网络方面两个容器共享, 其他的如文件系统, 进程等还是隔离开的.
4:none 模式,--net=none.
这个模式下, dokcer 不为容器进行任何网络配置. 需要我们自己为容器添加网卡, 配置 IP.
因此, 若想使用 pipework 配置 docker 容器的 ip 地址, 必须要在 none 模式下才可以
以下是几种分配 IP 的方式:
一, pipework
首先讲一下 docker 的网络模式:
我们使用 docker run 创建容器时, 可以使用 --net 选项指定容器的网络模式, docker 一共有 4 中网络模式:
1:bridge 模式,--net=bridge(默认).
这是 dokcer 网络的默认设置. 安装完 docker, 系统会自动添加一个供 docker 使用的网桥 docker0, 我们创建一个新的容器时, 容器通过 DHCP 获取一个与 docker0 同网段的 IP 地址. 并默认连接到 docker0 网桥, 以此实现容器与宿主机的网络互通. 如下:
2:host 模式,--net=host.
这个模式下创建出来的容器, 将不拥有自己独立的 Network Namespace, 即没有独立的网络环境. 它使用宿主机的 ip 和端口.
3:container 模式,--net=container:NAME_or_ID.
这个模式就是指定一个已有的容器, 共享该容器的 IP 和端口. 除了网络方面两个容器共享, 其他的如文件系统, 进程等还是隔离开的.
4:none 模式,--net=none.
这个模式下, dokcer 不为容器进行任何网络配置. 需要我们自己为容器添加网卡, 配置 IP.
因此, 若想使用 pipework 配置 docker 容器的 ip 地址, 必须要在 none 模式下才可以.
pipework 安装:
- # wget https://github.com/jpetazzo/pipework/archive/master.zip
- # unzip pipework-master.zip
- # cp pipework-master/pipework /usr/local/bin/
- # chmod +x /usr/local/bin/pipework
创建 none 模式的容器, 为其分配 IP.
- #ip a show docker0
- #docker run -idt --name test --net=none resin
- #pipework docker0 test 172.17.42.100/16@172.17.42.1
- #docker attach test
以上操作给新建的 test 容器分配了一个 172.17.42.100 的 IP 地址.
=============================================================================
二, docker 默认使用'bridge'来设置 container 的网络模式(即从与 docker0 同网段的未使用的 IP 中取一个作为 container 的 IP), 我们这里使用'none'来实现自己手动配置 container 的网络.
首先我们以 **--net='none'** 的方式启动一个 container
- [yaxin@cube2x ~]$docker run -i -t --rm --net='none' ubuntu /bin/bash
- root@db84e747c362:/# ifconfig -a
lo Link encap:Local Loopback
- inet addr:127.0.0.1 Mask:255.0.0.0
- inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
- collisions:0 txqueuelen:0
- RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
- root@db84e747c362:/#
可以看到, 由于我们使用'none'模式, container 中没有获取到 IP, 甚至连网卡都没有, 下面我们开始给 container 配置 IP
首先获取 container 的 pid(我们需要通过 pid 获取 file descriptor)
- [yaxin@cube2x ~]$docker ps
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- db84e747c362 docker.cn/docker/ubuntu:latest "/bin/bash" 4 minutes ago Up 4 minutes sharp_kirch
- [yaxin@cube2x ~]$docker inspect -f "{{.State.Pid}}" sharp_kirch
- 23090
ip-netns 的 man page 中有这样一句
By convention a named network namespace is an object at /var/run/netns/NAME that can be opened. The file descriptor resulting from opening/var/run/netns/NAME refers to the specified network namespace
因而我们需要创建一个链接
[yaxin@cube2x ~]$sudo ln -s /proc/23090/ns/net /var/run/netns/23090
然后创建一对端到端的网卡, 将 veth_db84e747c3 绑定到 docker0 网桥, 并启动. 将另一块网卡 X 放到 container 内部
- [yaxin@cube2x ~]$sudo ip link add veth_db84e747c3 type veth peer name X
- [yaxin@cube2x ~]$sudo brctl addif docker0 veth_db84e747c3
- [yaxin@cube2x ~]$sudo ip link set veth_db84e747c3 up
- [yaxin@cube2x ~]$sudo ip link set X netns 23090
这时查看 container 的 IP, 会发现多了一个名为 X 的网卡
root@db84e747c362:/# ifconfig -aX Link encap:Ethernet HWaddr 5a:7e:4d:ba:63:1c
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
- collisions:0 txqueuelen:1000
- RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
- inet addr:127.0.0.1 Mask:255.0.0.0
- inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
- collisions:0 txqueuelen:0
- RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
然后对 container 内部新添加的网卡进行配置(可以通过 man ip-netns 更详细查看)
- [yaxin@cube2x ~]$sudo ip netns exec 23090 ip link set dev X name eth0
- [yaxin@cube2x ~]$sudo ip netns exec 23090 ip link set eth0 up
- [yaxin@cube2x ~]$sudo ip netns exec 23090 ip addr add 172.17.111.10/16 dev eth0
- [yaxin@cube2x ~]$sudo ip netns exec 23090 ip route add default via 172.17.42.1
注意: 指定给 container 的 IP 必须跟 docker0 在同一网段, 且给 container 的网关应该为 docker0 的 IP
最后, 写成 shell 脚本如下:
- #!/usr/bin/env bash# filename: bind_addr.sh
- if [ `id -u` -ne 0 ];then
- echo '必须使用 root 权限'
- exitfi
- if [ $# != 2 ]; then
- echo "使用方法: $0 容器名字 IP"
- exit 1fi
- container_name=$1bind_ip=$2
- container_id=`docker inspect -f '{{.Id}}' $container_name 2> /dev/null`
- if [ ! $container_id ];then
- echo "容器不存在"
- exit 2fibind_ip=`echo $bind_ip | egrep '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$'`
- if [ ! $bind_ip ];then
- echo "IP 地址格式不正确"
- exit 3fi
- container_minid=`echo $container_id | cut -c 1-10`
container_netmask=`ip addr show docker0 | grep "inet\b" | awk '{print $2}' | cut -d / -f2`
container_gw=`ip addr show docker0 | grep "inet\b" | awk '{print $2}' | cut -d / -f1`
- bridge_name="veth_$container_minid"
- container_ip=$bind_ip/$container_netmask
- pid=`docker inspect -f '{{.State.Pid}}' $container_name 2> /dev/null`
- if [ ! $pid ];then
- echo "获取容器 $container_name 的 id 失败"
- exit 4fi
- if [ ! -d /var/run/netns ];then
- mkdir -p /var/run/netns
- fi
- ln -sf /proc/$pid/ns/net /var/run/netns/$pid
ip link add $bridge_name type veth peer name X
brctl addif docker0 $bridge_name
ip link set $bridge_name up
ip link set X netns $pid
ip netns exec $pid ip link set dev X name eth0
ip netns exec $pid ip link set eth0 up
ip netns exec $pid ip addr add $container_ip dev eth0
ip netns exec $pid ip route add default via $container_gw
运行并写入 ip 和容器名称
配置容器与主机 IP 同一网段
先配置主机 br0
- vi /etc/sysconfig/network-scripts/ifcfg-br0
- DEVICE=br0
- TYPE=Bridge
- BOOTPROTO=static
- ONBOOT=yes
- DELAY=0
- STP=yes
- IPADDR=192.168.2.111
- NETMASK=255.255.255.0
- GATEWAY=192.168.2.1
- /etc/init.d/network restart
- docker run -itd --name test centos /bin/bash
- pipework br0 test 192.168.2.201/24@192.168.2.1
来源: https://blog.csdn.net/wangdaoge/article/details/52703890