• 【转】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" | awk '{print $2}' | cut -d / -f2`
    container_gw=`ip addr show docker0 | grep "inet" | 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
  • 相关阅读:
    Spark 之 内存模型
    Python 之 windows上安装和pycharm 使用
    Kafka之 kafka消费->SparkStreaming|写入->Kafka|kafka消费->hbase
    SparkStreaming之 任务失败后,自动重启
    微信小程序常用赋值方法小结
    eclipse中xml文件Ctrl+左键不跳转解决办法
    SpringCloud简介以及相关组件
    spring怎么设置定时任务
    Http协议请求的不同类型
    Spring各个jar包作用
  • 原文地址:https://www.cnblogs.com/puremans/p/6415679.html
Copyright © 2020-2023  润新知