【轉】docker固定IP第二種方法


默認情況下啟動一個container,其會自動獲取一個跟docker0同網段的IP,而且重啟container其IP一般會發生變化,但有時候我們會需要固定的IP。要實現這個並不困難。

docker run啟動一個container的命令有一個--net的參數用於指定container的網絡類型

--net="bridge" Set the Network mode for the container      'bridge': creates a new network stack for the container on the docker bridge      'none': no networking for this container      'container:<name|id>': reuses another container network stack      'host': use the host network stack inside the container. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure.

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 -a X 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) root@db84e747c362:/# 

然后對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權限' exit fi if [ $# != 2 ]; then echo "使用方法: $0 容器名字 IP" exit 1 fi container_name=$1 bind_ip=$2 container_id=`docker inspect -f '{{.Id}}' $container_name 2> /dev/null` if [ ! $container_id ];then echo "容器不存在" exit 2 fi bind_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 3 fi 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 4 fi 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM