如何在Docker容器中设置静态IP地址?

我对docker默认给我的IP范围非常满意(176.17.xx),所以我不需要创build一个新的桥,我只是想给我的容器这个范围的静态地址,所以我可以点客户端浏览器直接。 我试过使用

RUN echo "auto eth0" >> /etc/network/interfaces RUN echo "iface eth0 inet static" >> /etc/network/interfaces RUN echo "address 176.17.0.250" >> /etc/network/interfaces RUN echo "netmask 255.255.0.0" >> /etc/network/interfaces RUN ifdown eth0 RUN ifup eth0 

从一个Dockerfile,并正确地填充接口文件,但接口本身并没有改变。 实际上,在容器中运行ifup eth0会得到这个错误:

RTNETLINK答案:操作不允许

无法启动eth0

我已经在这里https://stackoverflow.com/a/35359185/4094678回答了这个问题,但是我现在看到这个问题实际上比上面提到的那个更老了,所以我也要复制这个答案:;

使用Docker版本1.10.1可轻松构build9e83765。

首先你需要创build你自己的dockernetworking(mynet123)

 docker network create --subnet=172.18.0.0/16 mynet123 

比简单地运行图像(我将以ubuntu为例)

 docker run --net mynet123 --ip 172.18.0.22 -it ubuntu bash 

然后在ubuntu shell中

 ip addr 

另外你可以使用–hostname来指定一个主机名–add-host来添加更多的条目到/ etc / hosts

文档(以及为什么你需要创build一个networking)在https://docs.docker.com/engine/reference/commandline/network_create/

我使用官方的Docker文档写在这里的方法,我已经证实它的工作原理:

 # At one shell, start a container and # leave its shell idle and running $ sudo docker run -i -t --rm --net=none base /bin/bash root@63f36fc01b5f:/# # At another shell, learn the container process ID # and create its namespace entry in /var/run/netns/ # for the "ip netns" command we will be using below $ sudo docker inspect -f '{{.State.Pid}}' 63f36fc01b5f 2778 $ pid=2778 $ sudo mkdir -p /var/run/netns $ sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid # Check the bridge's IP address and netmask $ ip addr show docker0 21: docker0: ... inet 172.17.42.1/16 scope global docker0 ... # Create a pair of "peer" interfaces A and B, # bind the A end to the bridge, and bring it up $ sudo ip link add A type veth peer name B $ sudo brctl addif docker0 A $ sudo ip link set A up # Place B inside the container's network namespace, # rename to eth0, and activate it with a free IP $ sudo ip link set B netns $pid $ sudo ip netns exec $pid ip link set dev B name eth0 $ sudo ip netns exec $pid ip link set eth0 up $ sudo ip netns exec $pid ip addr add 172.17.42.99/16 dev eth0 $ sudo ip netns exec $pid ip route add default via 172.17.42.1 

使用这种方法,我总是用net = none来运行我的容器,并用外部脚本设置IP地址。

实际上,尽pipe我最初失败了,@ MarkO'Connor的回答是正确的。 我在我的主机/ etc / network / interfaces文件中创build了一个新的接口(docker0),在主机上运行sudo ifup docker0, 然后运行

 docker run --net=host -i -t ... 

它拿起静态IP并将其分配给容器中的docker0。

谢谢!

默认情况下,Docker容器没有足够的权限来操作networking堆栈。 您可以尝试添加–cap-add = NET_ADMIN到运行命令以允许此特定function。 或者你可以尝试–privileged = true(授予所有权利)进行testing。

另一个select是从主机使用pipe道 。

  • 设置你自己的桥 (如br0
  • 用以下命令启动docker-b=br0

& pipe道 ( 192.168.1.1以下是default gateway IP地址):

 pipework br0 container-name 192.168.1.10/24@192.168.1.1 

编辑:不要以--net=none开头:这将closures容器端口。

请参阅更多说明

这对我工作:

 docker run --cap-add=NET_ADMIN -d -it myimages/image1 /bin/sh -c "/sbin/ip addr add 172.17.0.8 dev eth0; bash" 

解释:

  • --cap-add=NET_ADMIN有pipe理networking的权限(比如/sbin/ip命令)

  • 容器的myimages/image1图像

  • /bin/sh -c "/sbin/ip addr add 172.17.0.8 dev eth0 ; bash"在容器内部运行ip addr add 172.17.0.8 dev eth0向此容器中添加一个新的ip地址172.17.0.8(注意:请使用现在将来的免费IP地址)。 然后运行bash,只是为了不让容器自动停止。

奖励

我的目标场景:设置分布式应用程序,容器在dist-app中扮演不同的angular色。 “导体容器”能够自行运行泊坞窗命令(内部),以根据需要启动和停止容器。 每个容器都被configuration为知道在哪里连接以访问dist-app中的特定angular色/容器(因此每个合作伙伴必须知道每个angular色的ip集合)。

去做这个:

  1. “导体容器”

用这个Dockerfile创build的图像

 FROM pin3da/docker-zeromq-node MAINTAINER Foobar # install docker software RUN apt-get -yqq update && apt-get -yqq install docker.io # export /var/run/docker.sock so we can connect it in the host VOLUME /var/run/docker.sock 

图像构build命令:

 docker build --tag=myimages/conductor --file=Dockerfile . 

容器运行命令:

 docker run -v /var/run/docker.sock:/var/run/docker.sock --name=conductor1 -d -it myimages/conductor bash 
  1. 运行具有不同angular色的容器。

首先(不是绝对必要的)添加条目到/etc/hosts来通过ip或name来定位合作伙伴(选项--add-host

第二个(显然是必需的)分配一个IP到正在运行的容器(使用/sbin/ip

 docker run --cap-add=NET_ADMIN --add-host worker1:172.17.0.8 --add-host worker2:172.17.0.9 --name=worker1 -h worker1.example.com -d -it myimages/image1 /bin/sh -c "/sbin/ip addr add 172.17.0.8 dev eth0; bash" 

我明白,在这个阶段你并没有考虑容器的多主机networking,但是我相信你可能很快就会需要它。 编织将允许您首先在一个主机上定义多个容器networking,然后将一些容器移动到另一个主机,而不会丢失分配给它的静态IP。

pipework也很棒,但如果你可以使用ip以外的主机名,那么你可以试试这个脚本

 #!/bin/bash # This function will list all ip of running containers function listip { for vm in `docker ps|tail -n +2|awk '{print $NF}'`; do ip=`docker inspect --format '{{ .NetworkSettings.IPAddress }}' $vm`; echo "$ip $vm"; done } # This function will copy hosts file to all running container /etc/hosts function updateip { for vm in `docker ps|tail -n +2|awk '{print $NF}'`; do echo "copy hosts file to $vm"; docker exec -i $vm sh -c 'cat > /etc/hosts' < /tmp/hosts done } listip > /tmp/hosts updateip 

每次启动Docker实验时,只需要运行这个命令你可以在这里find我的脚本,附加函数dockerip

我发现–net = host可能并不总是最好的select,因为它可能允许用户closures容器中的主机! 无论如何,事实certificate,我不能从内部做到这一点的原因是因为networkingconfiguration被devise为仅限于以–privileged = true参数开始的会话。

为了完整:在Docker论坛上提出了另一种方法。 (编辑:并通过АндрейСердюк的答案传递)。

主机系统上添加静态IP地址,然后将端口发布到该IP,例如docker run -p 192.0.2.1:80:80 -d mywebserver

当然,这种语法不适用于IPv6,文档没有提到…

这听起来是错误的:主机上常用的通配符(*:80)理论上与容器冲突。 在实践中,Docker端口优先,并不会冲突,因为它是如何使用iptables实现的。 但是您的公共容器IP仍然会在所有冲突的端口上响应,例如ssh。

您可以使用服务发现工具 – https://github.com/crosbymichael/skydock来设置SkyDns

或者:只需创buildnetworking接口,并像这里一样发布Docker容器端口https://gist.github.com/andreyserdjuk/bd92b5beba2719054dfe