前段时间,我一直在研究如何给docker分配静态ip,主要的用途是让thrift进来和出来都走一个ip,还有就是爬虫可以独立ip地址,这样就很好的实现了爬虫的多ip方式…  但是随着nginx tcp的加入和开发了一个基于python socket的ip轮询访问模块解决了这两个问题…  当然也不能因为这两问题,就丢弃这问题了….

在docker run的时候,咱们可以添加-p参数来控制他的source来源ip。   下面的命令,对外来说,开放了192.168.1.200:9200的端口…  但是我们不仅仅满与此。 docker run -p 端口的实现,就是借用iptables来实现的…   我们iptables -t nat -L 的时候,就能看到docker帮我做好的nat关系…. docker做iptables的prerouting的时候,是追加了名叫docker的自定义链条…      差点又跑题了,如果是桥接模式,那么就致使当我们如果容器里面端口的变动比较大的时候,那么就会造成改动端口映射的操作的复杂性,需要每次的变更,做一个iptables prerouting映射…    但是如果你选择HOST网络模式,那么你又不好确定你的app绑定的是哪个ip地址,不是什么服务端都支持bind ip地址的… 有些搓蛋的服务端就默认绑定第一个ip地址…    这个时候,为docker容器分配一个独立的静态ip地址就显得很有必要了….  反正就一个ip地址,你可劲的折腾…..    

Python

docker          run                   -         it                   -         p                   192.168.1.200         :         9200         :         9200                   redis         _cluster                   9200

Python

root         @         ubuntu         :         ~         # iptables -t nat -L -n


Chain          PREROUTING                   (         policy          ACCEPT         )


target              prot          opt          source                        destination


DOCKER              all                    --                    0.0.0.0         /         0                              0.0.0.0         /         0                              ADDRTYPE          match          dst         -         type                   LOCAL


                  


Chain          INPUT                   (         policy          ACCEPT         )


target              prot          opt          source                        destination


                  


Chain          OUTPUT                   (         policy          ACCEPT         )


target              prot          opt          source                        destination


DOCKER              all                    --                    0.0.0.0         /         0                             !         127.0.0.0         /         8                            ADDRTYPE          match          dst         -         type                   LOCAL


                  


Chain          POSTROUTING                   (         policy          ACCEPT         )


target              prot          opt          source                        destination


MASQUERADE           all                    --                    172.17.0.0         /         16                          0.0.0.0         /         0


MASQUERADE           all                    --                    172.17.0.0         /         16                         !         172.17.0.0         /         16


MASQUERADE           tcp                    --                    172.17.0.1                             172.17.0.1                             tcp          dpt         :         9200


                  


Chain          DOCKER                   (         2                   references         )


target              prot          opt          source                        destination


DNAT                tcp                    --                    0.0.0.0         /         0                              0.0.0.0         /         0                              tcp          dpt         :         9200                   to         :         172.17.0.1         :         9200

需要注意的是,docker run创建一个容器的时候,一定要把他的网卡模式改成docker的none…  一般在docker自定义网络的时候,都会把–net=none,再通过后期的一顿折腾让docker的容器有网络…..


接着,我如果想给容器,彻底的分配一个外网ip,或者管理ip,反正就一个静态的独立ip,怎么破? 用pipework是可以实现的。 但这东西稍复杂些,我们就先用系统的ip netns来解决…. 通过inspect我们知道了他的state pid . 

Python

root         @         ubuntu         :         ~         # docker ps -a


CONTAINER          ID                          IMAGE                        COMMAND                         CREATED                      STATUS                       PORTS                        NAMES


232621e9e9fb                          redis         _cluster                         "/app/manage.sh 9000   41 minutes ago      Up 41 minutes                           agitated_blackwell


root@ubuntu:~# docker inspect -f "         {         {         .         State         .         Pid         }         }"                   232621e9e9fb


4777


root         @         ubuntu         :         ~         # pid=4777

那么我们来开始绑定静态ip地址,先别看原理,暂时照着做…

Python

mkdir                   -         p                   /         var         /         run         /         netns


ln                   -         s                   /         proc         /         $         pid         /         ns         /         net                   /         var         /         run         /         netns         /         $         pid          ip          link          add                   A                   type                   veth          peer          name                   B


brctl          addif          docker0                   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                   192.168.1.200         /         24                   dev          eth0


ip          netns          exec                   $         pid          ip          route          add          default          via                   192.168.1.1


这些都结束了后,我们会发现容器的网卡里面从一个lo,多出一个eth0网卡,网卡的ip地址正是我们刚才绑定的192.168.1.200

Python

bash         -         4.1         # ip a


1         :                   lo         :                   <         LOOPBACK         ,         UP         ,         LOWER_UP         >                   mtu                   65536                   qdisc          noqueue          state          UNKNOWN


             link         /         loopback                   00         :         00         :         00         :         00         :         00         :         00                   brd                   00         :         00         :         00         :         00         :         00         :         00


             inet                   127.0.0.1         /         8                   scope          host          lo


                valid_lft          forever          preferred_lft          forever


             inet6                   ::         1         /         128                   scope          host


                valid_lft          forever          preferred_lft          forever


22         :                   eth0         :                   <         BROADCAST         ,         MULTICAST         ,         UP         ,         LOWER_UP         >                   mtu                   1500                   qdisc          pfifo_fast          state          UP          qlen                   1000


             link         /         ether          ca         :         aa         :         87         :         05         :         c9         :         5a                   brd          ff         :         ff         :         ff         :         ff         :         ff         :         ff


             inet                   192.168.1.200         /         24                   scope          global                   eth0


                valid_lft          forever          preferred_lft          forever


             inet6          fe80         ::         c8aa         :         87ff         :         fe05         :         c95a         /         64                   scope          link


                valid_lft          forever          preferred_lft          forever


bash         -         4.1         #

到此为止,docker绑定固定的静态ip的方法已经说明白了….   看了文章后,会发现docker绑定ip是比较的简单..  docker的网络是不怎么好理解的,这两天我多专供下docker分配ip的整个流程 (docker iptables)