【问题标题】:Assign static IP to Docker container为 Docker 容器分配静态 IP
【发布时间】: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 到这个容器时,它都不起作用。我可能遇到了什么问题?

【问题讨论】:

标签: docker


【解决方案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}}{{.IPAddress}}{{end}}' $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 服务:

  1. 我为 docker 主机上的所有服务创建 ip 别名
  2. 然后我运行每个服务,将端口从这个 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.20dns 容器,但除非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 上的容器的技术:

  1. Docker 服务应该以DOCKER_OPTS="--bridge=br0 --ip-masq=false --iptables=false" 启动。我假设 br0 网桥已经配置好了。

  2. 容器应该以--cap-add=NET_ADMIN --net=bridge开始

  3. /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
  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.]

    【讨论】:

    【解决方案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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-22
      • 2015-02-15
      • 2013-09-15
      • 2017-11-25
      • 2019-11-14
      • 1970-01-01
      相关资源
      最近更新 更多