如何让Docker容器获取外部DHCP服务器的IP地址

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何让Docker容器获取外部DHCP服务器的IP地址相关的知识,希望对你有一定的参考价值。

要重新再获得被分配IP地址,可以在客户端主机的DOC下(在[开始]-[运行]里输入“cmd”或点击附件里的[命令提示符]就可以进入) 输入命令 ipconfig/release (释放掉你获得的IP)
然后 ipconfig/renew(重新到DHCP服务器那里获得IP)

A类是第1段1-126,B类第1段是128-191,C类第1段就是192-223
A、B类被作为外网地址,C类被用做局域网地址。
你要连通外网后A、B类的都是网络经营商拥有的,你得花钱租的。

DHCP有一定的记忆性,如果只连一台计算机,肯定经常出现总分配同1个地址,或差不多的地址,以求网络的稳定,并节省消耗。
参考技术A 控件无法安装

如何从 docker 容器中获取 docker 主机的 IP 地址

【中文标题】如何从 docker 容器中获取 docker 主机的 IP 地址【英文标题】:How to get the IP address of the docker host from inside a docker container 【发布时间】:2014-05-21 14:20:26 【问题描述】:

正如标题所说。我需要能够检索 docker 主机的 IP 地址和从主机到容器的端口映射,并在容器内执行此操作。

【问题讨论】:

您能否详细说明您希望如何使用这些信息?您说的是“docker hosts”——您是否在多个主机上运行 Docker?一旦你的容器知道了主机的 IP 地址和端口映射,它会做什么? 将 docker 主机 IP 地址传递给 docker 容器的最简单方法,我认为您应该使用 'docker container exec' 在容器内进行调用。假设你想从busybox容器内ping主机,例如: $ IP = '8.8.8.8' && docker container busybox ping $IP ' 找出主机IP的方法,用你喜欢的。 【参考方案1】:

我的解决方案:

docker run --net=host

然后在 docker 容器中:

主机名-I | awk 'print $1'

【讨论】:

【参考方案2】:
docker network inspect bridge -f 'range .IPAM.Config.Gatewayend'

可以使用 docker network inspect 检索它

【讨论】:

迄今为止的最佳答案,因为它不依赖于容器中存在的任何二进制文件。【参考方案3】:

更新:在 Docker for Mac 上,从 18.03 版开始,您可以使用 host.docker.internal 作为主机的 IP。见aljabear's answer。对于 Docker for Mac 的早期版本,以下答案可能仍然有用:

在 Docker for Mac 上,docker0 网桥不存在,因此此处的其他答案可能不起作用。但是,所有传出流量都通过您的父主机路由,因此只要您尝试连接到它识别为自身的 IP(并且 docker 容器不认为是自身),您就应该能够连接。例如,如果您从父计算机运行它:

ipconfig getifaddr en0

这应该会向您显示 Mac 在其当前网络上的 IP,并且您的 docker 容器也应该能够连接到该地址。如果这个 IP 地址发生变化,这当然会很痛苦,但是您可以通过在父计算机上执行类似的操作,向您的 Mac 添加一个容器认为不是其自身的自定义环回 IP:

sudo ifconfig lo0 alias 192.168.46.49

然后,您可以使用 telnet 从 docker 容器中测试连接。就我而言,我想连接到远程 xdebug 服务器:

telnet 192.168.46.49 9000

现在,当流量进入您的 Mac 时,地址为 192.168.46.49(并且所有离开容器的流量都会通过您的 Mac),您的 Mac 将假定 IP 是它自己。当您使用完这个 IP 后,您可以像这样删除环回别名:

sudo ifconfig lo0 -alias 192.168.46.49

需要注意的一点是,如果 docker 容器认为流量的目的地是它自己,它就不会将流量发送到父主机。所以如果遇到问题,请检查容器内部的环回接口:

sudo ip addr show lo

就我而言,这显示了inet 127.0.0.1/8,这意味着我无法使用127.* 范围内的任何IP。这就是我在上面的示例中使用192.168.* 的原因。确保您使用的 IP 不会与您自己网络上的某些内容发生冲突。

【讨论】:

这个主机名的使用没有意义,因为它在 Docker for Linux 下不起作用。为什么他们不为 Linux 也添加它? 他们现在正在调查它@TheFox:github.com/docker/libnetwork/pull/2348 我的容器中不存在 telnet 命令【参考方案4】:

大多数希望自动执行此操作的应用的标准最佳做法是:您不需要。相反,您让运行容器的人注入外部主机名/IP 地址作为配置,例如作为环境变量或配置文件。允许用户注入它可以为您提供最便携的设计。

为什么会这么难?因为容器将在设计上将应用程序与主机环境隔离开来。默认情况下,网络仅被命名为该容器,并且主机的详细信息受到保护,不受容器内运行的进程的影响,这些进程可能不完全受信任。


根据您的具体情况有不同的选择:

如果您的容器在主机网络中运行,那么您可以直接查看主机上的路由表以查看默认路由。来自this question,以下对我有用,例如:

ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'

在容器中显示主机网络的示例如下所示:

docker run --rm --net host busybox /bin/sh -c \
  "ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'"

对于当前版本的 Docker Desktop,他们将 DNS 条目注入嵌入式 VM:

getent hosts host.docker.internal | awk 'print $1'

在 20.10 版本中,如果您使用额外选项运行容器,host.docker.internal 别名也可以在 Linux 上运行:

docker run --add-host host.docker.internal:host-gateway ...

如果您在云环境中运行,您可以从云提供商处查看元数据服务,例如AWS 一:

curl http://169.254.169.254/latest/meta-data/local-ipv4

如果您想要您的外部/互联网地址,您可以查询远程服务,例如:

curl ifconfig.co

每一个都有限制,并且只在特定场景下有效。最便携的选项仍然是使用作为配置注入的 IP 地址运行您的容器,例如这是在主机上运行较早的ip 命令并将其作为环境变量注入的选项:

export HOST_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p')
docker run --rm -e HOST_IP busybox printenv HOST_IP

【讨论】:

【参考方案5】:

AFAIK,对于 Docker for Linux(标准发行版),主机的 IP 地址将始终为172.17.0.1(在 docker 的主网络上,请参阅 cmets 了解更多信息) .

获取它的最简单方法是从主机通过ifconfig(接口 docker0):

ifconfig

在 docker 内部,来自 docker 的以下命令:ip -4 route show default | cut -d" " -f3

您可以使用以下命令行在 docker 中快速运行它:

# 1. Run an ubuntu docker
# 2. Updates dependencies (quietly)
# 3. Install ip package   (quietly)
# 4. Shows (nicely) the ip of the host
# 5. Removes the docker (thanks to `--rm` arg)
docker run -it --rm ubuntu:20.10 bash -c "apt-get update > /dev/null && apt-get install iproute2 -y > /dev/null && ip -4 route show default | cut -d' ' -f3"

【讨论】:

这适用于附加到docker0 默认桥接接口的容器。使用 Docker Compose 建立的容器并非如此,它不会存在于默认的桥接接口上。 docker network lsdocker network inspect <network_name> 可以帮助您确定 IP 将是什么。 感谢您的指示。顺便说一句,我在 linux 上,我期望 172.17.0.1,实际上我正在检查一个容器,它有 172.23.0.1。运行容器的数量是否会通过增加 ip 号来影响主机的映射方式? @funder7 这实际上取决于您在 docker 中使用的网络。你可以使用docker network ls访问网络,如果你没有定义任何网络,只要知道docker-compose在docker内部自动定义了虚拟网络(你也可以列出)。 @Nek 可能是我的错,我正在查看容器的内部 ip,而我的 docker0 网络接口是 172.17.0.1,无论如何我使用了现在支持 linux 的 docker.host.internal。不过谢谢你的命令,我会试试看的!【参考方案6】:

这是 Node.js 中的一个简约实现,适用于在 AWS EC2 实例 上运行主机的用户,使用前面提到的 EC2 Metadata instance

const cp = require('child_process');
const ec2 = function (callback) 
    const URL = 'http://169.254.169.254/latest/meta-data/local-ipv4';
    // we make it silent and timeout to 1 sec
    const args = [URL, '-s', '--max-time', '1'];
    const opts = ;
    cp.execFile('curl', args, opts, (error, stdout) => 
        if (error) return callback(new Error('ec2 ip error'));
        else return callback(null, stdout);
    )
        .on('error', (error) => callback(new Error('ec2 ip error')));
//ec2

并用作

ec2(function(err, ip) 
        if(err) console.log(err)
        else console.log(ip);
    )

【讨论】:

【参考方案7】:

从 18.03 版本开始,您可以使用 host.docker.internal 作为主机的 IP。

适用于 Docker for MacDocker for Windows,或许也适用于其他平台。

这是针对 Mac 的 docker.for.mac.localhost 的更新,从 17.06 版开始提供,docker.for.mac.host.internal 从 17.12 版开始提供,它们可能仍可在该平台上运行。

请注意,与 Mac 和 Windows 文档中一样,这仅用于开发目的。

例如,我在主机上设置了环境变量:

MONGO_SERVER=host.docker.internal

在我的docker-compose.yml 文件中,我有这个:

version: '3'

services:
  api:
    build: ./api
    volumes:
      - ./api:/usr/src/app:ro
    ports:
      - "8000"
    environment:
      - MONGO_SERVER
    command: /usr/local/bin/gunicorn -c /usr/src/app/gunicorn_config.py -w 1 -b :8000 wsgi

【讨论】:

@allanberry 不幸的是,Docker 人员不喜欢给我们提供一种独立于平台的方式来做到这一点,因为他们不喜欢使用非预期的用例(比如从 docker 容器访问本地机器上的任何服务) 我被介绍给 Docker,就像 构建一次,到处运行。 但这完全是错误的,因为您还必须始终配置主机系统。所以docker.for.mac.. 毫无用处,因为在大多数情况下,您的公司中没有仅限 Linux 或 Mac 的环境。它是混合的,您有使用 Linux、Mac 和 Windows 的开发人员。这个域没有任何意义,因为在 99% 的情况下它是一个混合主机操作系统环境。我没有在 macOS 下开发容器并将其部署到 macOS 服务器。我将它部署到 Linux。这是每个人都会做的。 那么docker.for.mac.. 的全部意义是什么? host.docker.internal does work on Docker for Windows 也是如此,至少在撰写此评论时是这样。 @joanlofe 遗憾的是,它不再起作用了。于 19.03.2 测试。 host.docker.internal 为我工作(Windows 10、WSL2 Ubuntu 20.04、Laravel Sail)【参考方案8】:

试试这个:

docker run --rm -i --net=host alpine ifconfig

【讨论】:

【参考方案9】:

所以...如果您使用 Rancher 服务器运行容器,Rancher v1.6(不确定 2.0 是否有此功能)容器可以访问 http://rancher-metadata/,其中包含很多有用的信息。

可以在容器内部找到 IP 地址: curl http://rancher-metadata/latest/self/host/agent_ip

更多详情见: https://rancher.com/docs/rancher/v1.6/en/rancher-services/metadata-service/

【讨论】:

【参考方案10】:

适用于 Mac 和 Windows 的 TLDR

docker run -it --rm alpine nslookup host.docker.internal

...打印主机的IP地址...

nslookup: can't resolve '(null)': Name does not resolve

Name:      host.docker.internal
Address 1: 192.168.65.2

详情

在Mac 和Windows 上,您可以使用特殊的DNS 名称host.docker.internal

主机有一个不断变化的 IP 地址(如果您没有网络访问权限,则没有)。从 18.03 开始​​,我们的建议是连接到特殊的 DNS 名称 host.docker.internal,它解析为主机使用的内部 IP 地址。这是出于开发目的,不适用于 Docker Desktop for Mac 之外的生产环境。

【讨论】:

请不要添加same answer to multiple questions。一旦您获得足够的声誉,就回答最好的一个并将其余的标记为重复。如果不是重复的,请根据问题调整帖子并标记以取消删除。【参考方案11】:

我有 Ubuntu 16.03。对我来说

docker run --add-host dockerhost:`/sbin/ip route|awk '/default/  print  $3'` [image]

工作(生成错误的 ip)

我的工作解决方案是:

docker run --add-host dockerhost:`docker network inspect --format='range .IPAM.Config.Gatewayend' bridge` [image]

【讨论】:

【参考方案12】:

在 Ubuntu 上,hostname 命令可以与以下选项一起使用:

-i, --ip-address 主机名地址 -I, --all-ip-addresses 主机的所有地址

例如:

$ hostname -i
172.17.0.2

要分配给变量,可以使用以下单行:

IP=$(hostname -i)

【讨论】:

这将为您提供 Docker 容器的 IP 地址,而不是主机的 IP 地址【参考方案13】:

我使用的解决方案是基于一个“服务器”,当它收到一个http请求时,它会返回Docker主机的外部地址。

在“服务器”上:

1) 启动 jwilder/nginx-proxy

# docker run -d -p <external server port>:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy

2) 启动 ipify 容器

# docker run -e VIRTUAL_HOST=<external server name/address> --detach --name ipify osixia/ipify-api:0.1.0

现在当容器向服务器发送 http 请求时,例如

# curl http://<external server name/address>:<external server port>

ipify通过http头“X-Forwarded-For”返回Docker主机的IP地址

示例(ipify 服务器的名称为“ipify.example.com”并在端口 80 上运行,docker 主机的 IP 为 10.20.30.40):

# docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
# docker run -e VIRTUAL_HOST=ipify.example.com --detach --name ipify osixia/ipify-api:0.1.0

现在可以在容器内调用:

# curl http://ipify.example.com
10.20.30.40

【讨论】:

【参考方案14】:

也许我创建的容器也很有用https://github.com/qoomon/docker-host

您可以简单地使用容器名称 dns 来访问主机系统,例如curl http://dockerhost:9200,因此无需为任何 IP 地址而烦恼。

【讨论】:

【参考方案15】:

如果您想要Windows 上的真实IP 地址(不是网桥IP)并且您有docker 18.03(或更新的),请执行以下操作:

在镜像名称为 nginx 的主机上运行 bash(适用于 Alpine Linux distribution):

 docker run -it nginx /bin/ash

然后在容器内运行

/ # nslookup host.docker.internal

Name:      host.docker.internal
Address 1: 192.168.65.2

192.168.65.2 是主机的 IP - 而不是像 spinus 接受的答案中的网桥 IP。

我在这里使用host.docker.internal:

主机有一个不断变化的 IP 地址(如果您没有网络访问权限,则没有)。从 18.03 开始​​,我们的建议是连接到特殊的 DNS 名称 host.docker.internal,它解析为主机使用的内部 IP 地址。这是出于开发目的,不适用于 Docker for Windows 之外的生产环境。

【讨论】:

我试过你的解决方案,似乎找不到nslookup命令 @Sergey 你的图片是基于Alpine Linux 的吗?如果没有,请检查您的特定 linux distribution 的等效项。 不,我完全使用你的命令 - docker run -it nginx /bin/ash 好的 - 如果你在 Windows 上,那么我切换到 linux containers 并且我没有使用 windows containers。你可以通过右键单击 docker icon 并选择 Switch to Linux containers 来做到这一点。我认为这在您下载图像时可能很重要。如果您有windows container,请检查是否删除旧的nginx 图像并再次下载它会为您提供另一个容器。如果它仍然对您不起作用 - 您可以尝试在 ash 中安装 nslookup 如果不能做 nslookup,就做 ping。它将显示已解析的 IP。对我来说,这个答案有效,我只是在容器内使用这个主机名(host.docker.internal【参考方案16】:

这是我的做法。在这种情况下,它会在 docker 映像中的 /etc/hosts 中添加一个主机条目,将 taurus-host 指向我的本地计算机 IP::

TAURUS_HOST=`ipconfig getifaddr en0`
docker run -it --rm -e MY_ENVIRONMENT='local' --add-host "taurus-host:$TAURUS_HOST" ...

然后,在 Docker 容器中,脚本可以使用主机名 taurus-host 来访问我的本地机器,该机器托管 docker 容器。

【讨论】:

【参考方案17】:

在linux下你可以运行

HOST_IP=`hostname -I | awk 'print $1'`

在 macOS 中,您的主机不是 Docker 主机。 Docker 将在 VirtualBox 中安装它的主机操作系统。

HOST_IP=`docker run busybox ping -c 1 docker.for.mac.localhost | awk 'FNR==2 print $4' | sed s'/.$//'`

【讨论】:

第一个代码块将获取容器 IP 而不是主机 IP mandoc of hostname -I 警告不要“对输出的顺序做任何假设。”【参考方案18】:

如果您在 Service Fabric 群集上运行 Windows 容器,则主机的 IP 地址可通过环境变量 Fabric_NodeIPOrFQDN 获得。 Service Fabric environment variables

【讨论】:

【参考方案19】:

Docker for Mac 我想从容器连接到主机上的服务

主机有一个不断变化的 IP 地址(如果您没有网络访问权限,则没有)。从 18.03 开始​​,我们的建议是连接到特殊的 DNS 名称 host.docker.internal,它解析为主机使用的内部 IP 地址。

网关也可以通过 gateway.docker.internal 访问。 https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds

【讨论】:

【参考方案20】:

对于那些在 AWS 中运行 Docker 的人来说,这是另一种选择。此选项避免使用 apk 添加 curl 包并节省宝贵的 7mb 空间。使用内置的 wget(整体 BusyBox 二进制文件的一部分):

wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4

【讨论】:

【参考方案21】:

https://docs.docker.com/machine/install-machine/

a) $ docker-machine ip

b) 获取一台或多台机器的 IP 地址。

  $ docker-machine ip host_name

  $ docker-machine ip host_name1 host_name2

【讨论】:

这会检索运行 docker 容器的虚拟机的 IP,而不是运行容器的主机的 IP。 这仅适用于在 docker-machine 上运行的 docker。新的 docker for mac 不能在 docker-machine 上运行。【参考方案22】:

如果你启用了docker remote API(例如通过-Htcp://0.0.0.0:4243)并且知道主机的主机名或IP地址,这可以通过大量的bash来完成。

在我容器的用户bashrc内:

export hostIP=$(ip r | awk '/default/print $3')
export containerID=$(awk -F/ '/docker/print $NF;exit;' /proc/self/cgroup)
export proxyPort=$(
  curl -s http://$hostIP:4243/containers/$containerID/json |
  node -pe 'JSON.parse(require("fs").readFileSync("/dev/stdin").toString()).NetworkSettings.Ports["DESIRED_PORT/tcp"][0].HostPort'
)

第二行从本地 /proc/self/cgroup 文件中获取容器 ID。

第三行卷曲到主机(假设您使用 4243 作为 docker 的端口)然后使用节点解析返回的 JSON 以获取 DESIRED_PORT

【讨论】:

这仅适用于您使用端口转发的情况。实际上HostPort 在这里可能是有用的信息,不幸的是HostIp 可能是0.0.0.0【参考方案23】:

对于那些在 AWS 中运行 Docker 的人,主机的 instance meta-data 仍然可以从容器内部获得。

curl http://169.254.169.254/latest/meta-data/local-ipv4

例如:

$ docker run alpine /bin/sh -c "apk update ; apk add curl ; curl -s http://169.254.169.254/latest/meta-data/local-ipv4 ; echo"
fetch http://dl-cdn.alpinelinux.org/alpine/v3.3/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.3/community/x86_64/APKINDEX.tar.gz
v3.3.1-119-gb247c0a [http://dl-cdn.alpinelinux.org/alpine/v3.3/main]
v3.3.1-59-g48b0368 [http://dl-cdn.alpinelinux.org/alpine/v3.3/community]
OK: 5855 distinct packages available
(1/4) Installing openssl (1.0.2g-r0)
(2/4) Installing ca-certificates (20160104-r2)
(3/4) Installing libssh2 (1.6.0-r1)
(4/4) Installing curl (7.47.0-r0)
Executing busybox-1.24.1-r7.trigger
Executing ca-certificates-20160104-r2.trigger
OK: 7 MiB in 15 packages
172.31.27.238

$ ifconfig eth0 | grep -oP 'inet addr:\K\S+'
172.31.27.238

【讨论】:

这对于使用 AWS 的人来说是一种超级方便的方法。我用它来配置 Consul 代理的客户端和绑定地址。当您处于无法使用主机网络的情况下(例如在 Elastic Beanstalk 和 ECS 中部署容器)时,它是理想的选择。 这是救命稻草,谢谢。我无法弄清楚如何处理我的 ECS 集群中的容器之间的通信。 在 Phusion basimage(基于 ubuntu)上,我不得不稍微改变你的命令:ifconfig eth0 | grep -oP 'inet \K\S+' 如果 docker 有这样的东西那就太棒了 对于fargate,您必须在169.254.170.2/v2/metadata的json响应中搜索“IPv4Addresses”【参考方案24】:
/sbin/ip route|awk '/default/  print $3 '

正如@MichaelNeale 所注意到的,在Dockerfile 中使用此方法没有意义(除非我们仅在构建期间需要此IP),因为此IP 将在构建期间进行硬编码。

【讨论】:

当您对容器使用 docker 网桥(默认)时,这将输出 172.17.42.1 之类的网桥 IP,而不是 192.168.1.x 之类的主机 IP(我假设您的主机位于家庭 NAT 上)。如果您想要 192.168.1.x 地址,使用@Magno Torres 答案可能是人们在这种情况下想要的。 RUN 不会像你期望的那样工作 - 它只会在构建时计算 IP - 并且在那之后将永远是静态的,并且没有用。它将是构建主机的 IP。 @Programster,我可以假设人们想要 docker 主机和容器之间的连接,这就是桥 IP 可以给你的(当然在标准的“家庭”安装中)。如果它甚至可以在 docker bridge 之外并且无法访问,为什么有人需要“真实”主机 IP?这是所有刚安装 docker 并想在短时间内使用它的人的解决方案。 @MichaelNeale,和以前一样,我认为大多数开始使用 docker 的人都需要在他们的主机和容器之间建立连接,就是这样。如果有人在做“正确”的部署,可能他并没有使用 docker bridge,他使用的是自定义网络,而且他可能知道所有的网络怪癖或者他们设置了 DNS(或任何发现)。 @spinus - 但这只有在它在构建它的主机上运行时才有效 - 在这种情况下 - 你可以硬编码它 - 或查找它 - 我认为它不是一个有用的答案,会误导很多人 - 建议您删除它。 (运行位)【参考方案25】:

--add-host 可能是更简洁的解决方案(但没有端口部分,只有主机可以使用此解决方案处理)。因此,在您的 docker run 命令中,执行以下操作:

docker run --add-host dockerhost:`/sbin/ip route|awk '/default/  print  $3'` [my container]

(来自https://***.com/a/26864854/127400)

【讨论】:

当其他人想在 /etc/hosts 中添加条目时,我说“为此而生”;在这个问题上,这不是真的。 OP 还要求提供“主机和端口映射”,而您只覆盖了主机。 好的。我有点困惑,因为公认的解决方案也只涵盖主机部分。而且我认为您的解决方案优于棘突的解决方案。 如果你想使用 dind - docker-in-docker,这不起作用。内部 docker 会有不同的 ip【参考方案26】:

唯一的方法是在创建容器时将主机信息作为环境传递

run --env <key>=<value>

【讨论】:

更具体地说,可以使用如下命令行选项传入网桥 IP 地址:-e "DOCKER_HOST=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')"(使用来自unix.stackexchange.com/questions/87468/… 的接受答案) 我认为它不适用于 Docker for Mac / Windows。 (网桥IP)

以上是关于如何让Docker容器获取外部DHCP服务器的IP地址的主要内容,如果未能解决你的问题,请参考以下文章

如何在docker容器中连接外部mysql服务器

如何在没有端口映射的情况下将 docker 容器的 ip 和端口暴露给外部 docker 主机?

如何解决docker宿主机无法访问容器中的服务

为 docker 容器分配 IP 地址?

我可以在我的 docker 容器中获取 IP 地址吗?

结合Docker运行Spring Cloud微服务的多种方式