为 Docker 容器分配静态 IP
Posted
技术标签:
【中文标题】为 Docker 容器分配静态 IP【英文标题】:Assign static IP to Docker container 【发布时间】:2015-03-12 07:07:31 【问题描述】:我现在尝试在启动 Docker 容器时分配静态 IP 172.17.0.1。
我使用 2122 端口作为这个容器的 ssh 端口,以便让这个容器监听 2122 端口。
sudo docker run -i -t -p 2122:2122 ubuntu
这个命令将运行一个带有随机 IP 的 Docker 容器,比如 172.17.0.5,但是我需要为容器分配一个特定的 IP。
以下shell脚本是我在高级网络设置中参考的Docker文档。
pid=$(sudo docker inspect -f '.State.Pid' <container_name> 2>/dev/null)
sudo rm -rf /var/run/netns/*
sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid
sudo ip link add A type veth peer name B
sudo brctl addif docker0 A
sudo ip link set A up
sudo ip link set B netns $pid
sudo ip netns exec $pid ip link set eth0 down
sudo ip netns exec $pid ip link delete eth0
sudo ip netns exec $pid ip link set dev B name eth0
sudo ip netns exec $pid ip link set eth0 address 12:34:56:78:9a:bc
sudo ip netns exec $pid ip link set eth0 down
sudo ip netns exec $pid ip link set eth0 up
sudo ip netns exec $pid ip addr add 172.17.0.1/16 dev eth0
sudo ip netns exec $pid ip route add default via 172.17.42.1
这个 shell 脚本将分配一个静态 IP 172.17.0.1 并链接到世界。但是每当我尝试从本地 ssh 到这个容器时,它都不起作用。我可能遇到了什么问题?
【问题讨论】:
这个问题恐怕没有简单的答案,见github.com/docker/docker/issues/6743和github.com/docker/docker/issues/1179,读github.com/jpetazzo/pipework @larrylo 你能确认你在容器内启动了一个 sshd 吗? 您正在撤消 docker 守护进程为您执行的所有路由。容器不是虚拟机。 是的,我确认我可以在容器内启动 sshd How can I set a static IP address in a Docker container?的可能重复 【参考方案1】:轻松使用 Docker 版本 1.10.1,构建 9e83765。
首先您需要创建自己的 docker 网络 (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 添加更多条目
文档(以及为什么需要创建网络)https://docs.docker.com/engine/reference/commandline/network_create/
【讨论】:
很好的答案 - 只需添加一些附加信息:blog.jessfraz.com/post/ips-for-all-the-things @cantSleepNow 出于某种原因,我只需要使用我自己默认创建的网桥 br0,它是在系统启动期间在接口文件中创建的(因此它不是使用 docker network create 创建的),你能建议我如何我可以在不使用 docker 创建网桥的情况下获得与 --ip 参数相同的效果(获取容器的固定 IP 地址)吗? @MohammedNoureldin 我不完全理解 - 听起来也是一个新问题,我认为你应该这样问。 @cantSleepNow 我的意思是我需要修复容器的 IP 地址,尽管我没有使用自定义网桥(所以不能使用 --ip 参数),您有什么方法可以解决这个问题吗? @MohammedNoureldin 我不确定。正如我所说,将您的问题作为问题而不是评论发布 - 也许有人知道答案。【参考方案2】:对于docker-compose
,您可以使用以下docker-compose.yml
version: '2'
services:
nginx:
image: nginx
container_name: nginx-container
networks:
static-network:
ipv4_address: 172.20.128.2
networks:
static-network:
ipam:
config:
- subnet: 172.20.0.0/16
#docker-compose v3+ do not use ip_range
ip_range: 172.28.5.0/24
您可以使用以下主机进行测试:
docker-compose up -d
curl 172.20.128.2
现代docker-compose
不会那么频繁地更改 IP 地址。
要在一行中查找docker-compose
中所有容器的 ip,请使用:
for s in `docker-compose ps -q`; do echo ip of `docker inspect -f ".Name" $s` is `docker inspect -f 'range .NetworkSettings.Networks.IPAddressend' $s`; done
如果你想自动化,你可以使用类似example gist的东西
【讨论】:
看起来这只适用于 docker-compose v2,v3 破坏了兼容性。 使用docker-compose v3+时删除ip_range
我没有得到 ip_range。这不是被子网覆盖吗?无论如何,谢谢你!这解决了我的“我必须再次查找我的 mongo 容器的 ip” - 问题
有没有办法在compose版本3中指定ip地址?
如果没有ip_range
,该解决方案对我来说效果很好。我正在使用版本:'3.4'。【参考方案3】:
不是直接的答案,但它可以提供帮助。
我使用下一种方法运行与自己的静态 ips 绑定的大部分 dockerized 服务:
-
我为 docker 主机上的所有服务创建 ip 别名
然后我运行每个服务,将端口从这个 ip 重定向到容器中,这样每个服务都有自己的静态 ip,可供外部用户和其他容器使用。
示例:
docker run --name dns --restart=always -d -p 172.16.177.20:53:53/udp dns
docker run --name registry --restart=always -d -p 172.16.177.12:80:5000 registry
docker run --name cache --restart=always -d -p 172.16.177.13:80:3142 -v /data/cache:/var/cache/apt-cacher-ng cache
docker run --name mirror --restart=always -d -p 172.16.177.19:80:80 -v /data/mirror:/usr/share/nginx/html:ro mirror
...
【讨论】:
谢谢~我知道了。就像github.com/brandon-rhodes/fopnp/tree/m/playground 一样。我会试试的。 这是一个很好的解决方案,我只是附上这个链接让新用户了解别名cyberciti.biz/faq/… 感谢您的出色解决方案。 我不清楚这个答案在 OP 的上下文中如何有用。问题是关于为容器分配一个静态 IP 地址,即172.16.177.20
给dns
容器,但除非dns
容器已经分配了172.16.177.20
,否则此处的命令将不起作用。确保 dns 容器实际获取 IP 地址172.16.177.20
的部分在哪里?我错过了什么?【参考方案4】:
我在尝试 dockerise Avahi 时偶然发现了这个问题,它需要知道其公共 IP 才能正常运行。由于 Docker 中的 lack of support for static IP assignment,为容器分配静态 IP 很棘手。
This article 描述了如何将静态 IP 分配给Debian 上的容器的技术:
Docker 服务应该以DOCKER_OPTS="--bridge=br0 --ip-masq=false --iptables=false"
启动。我假设 br0
网桥已经配置好了。
容器应该以--cap-add=NET_ADMIN --net=bridge
开始
/etc/network/interfaces
中的容器 pre-up ip addr flush dev eth0
可用于关闭 Docker 分配的 IP 地址,如下例所示:
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
pre-up ip addr flush dev eth0
address 192.168.0.249
netmask 255.255.255.0
gateway 192.168.0.1
-
容器的入口脚本应该以
/etc/init.d/networking start
开头。此外,入口脚本需要编辑或填充 /etc/hosts
文件,以删除对 Docker 分配的 IP 的引用。
【讨论】:
【参考方案5】:这对我有用。
创建一个网络
docker network create --subnet=172.17.0.0/16 selnet
运行 docker 镜像
docker run --net selnet --ip 172.18.0.2 hub
一开始,我明白了
docker: Error response from daemon: Invalid address 172.17.0.2: It does not belong to any of this network's subnets.
ERRO[0000] error waiting for container: context canceled
解决方案:增加第二个四倍的 IP [.18.而不是 .17.]
【讨论】:
本页其他地方有 2 岁以上类似/相同的答案:***.com/a/35359185/694469【参考方案6】:你可以在运行的时候设置IP。
docker run --cap-add=NET_ADMIN -dit imagename /bin/sh -c "/sbin/ip addr add 172.17.0.12 dev eth0; bash"
在https://github.com/RvdGijp/mariadb-10.1-galera查看我的示例
【讨论】:
不幸的是这增加了一个IP地址,如果在之前的过程中分配了一个IP地址,这将导致有两个IP地址【参考方案7】:您可以通过名称访问其他容器的服务(ping apache
将获得 ip 或 curl http://apache
将访问 http 服务)这可以替代静态 ip。
【讨论】:
在 1.8 的 docker 版本中可以直接使用。在较新的版本中,您必须首先链接这些容器。【参考方案8】:如果您希望您的容器拥有自己的虚拟以太网套接字(具有自己的 MAC 地址)、iptables,则使用 Macvlan 驱动程序。这可能需要将流量路由到您的/ISP 路由器。
https://docs.docker.com/engine/userguide/networking/get-started-macvlan
【讨论】:
以上是关于为 Docker 容器分配静态 IP的主要内容,如果未能解决你的问题,请参考以下文章