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

xia*_*amx 317 ip docker

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

spi*_*nus 290

/sbin/ip route|awk '/default/ { print $3 }'
Run Code Online (Sandbox Code Playgroud)

正如@MichaelNeale所注意到的那样,使用这种方法是没有意义的Dockerfile(除非我们在构建时只需要这个IP),因为这个IP在构建期间将被硬编码.

  • 当您使用docker bridge(默认)作为容器时,这将输出网桥IP,如172.17.42.1,而不是主机的IP,如192.168.1.x(我假设您的主机在主NAT上).使用@Magno Torres答案可能是人们在这种情况下想要的192.168.1.x地址. (46认同)
  • @Programster,我可以假设人们想要docker主机和容器之间的连接,这就是桥接IP可以给你的东西(当然是标准的"home"安装).为什么有人会需要"真正的"主机IP,如果它甚至可以在docker bridge之外并且无法访问?这是所有刚刚安装了docker并希望在短时间内玩它的人的解决方案. (5认同)
  • RUN将无法按您预期的那样工作-它只会在构建时计算IP-此后将永远是静态的,并且没有用。这将是构建主机的IP。 (2认同)
  • @MichaelNeale,和以前一样,我认为大多数开始使用 docker 的人都需要在他们的主机和容器之间建立连接,就是这样。如果有人在进行“适当的”部署,那么他可能没有使用 docker 桥接器,而是使用自定义网络,并且可能他知道所有网络怪癖,或者他们设置了 DNS(或任何发现)。 (2认同)

all*_*rry 150

Docker for Mac上,从版本18.03开始,您可以将其host.docker.internal用作主机的IP.

请注意,如文档中所述,"这是用于开发目的[s],并且不适用于Docker for Mac之外的生产环境." 这是因为,在Docker for Mac中,"您无法在主机上看到docker0接口.此接口实际上位于虚拟机内."

这是docker.for.mac.localhost自版本17.06以来可用的更新,并且docker.for.mac.host.internal自版本17.12起可用,它仍然可以工作.

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

MONGO_SERVER=host.docker.internal
Run Code Online (Sandbox Code Playgroud)

在我的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
Run Code Online (Sandbox Code Playgroud)

  • 我被介绍给Docker,就像_Build它一样,在任何地方运行它._但这是非常错误的,因为你总是需要配置主机系统.所以`docker.for.mac..`是没用的,因为在大多数情况下你的公司没有Linux或Mac环境.它是混合的,你有开发人员使用Linux和Mac和Windows.这个域毫无意义,因为在99%它是一个混合的主机操作系统环境.我没有在macOS下开发容器并将其部署到macOS服务器.我将它部署到Linux.这就是每个人的所作所为.**那么甚至"docker.for.mac.."的全部内容甚至是什么?** (16认同)
  • @allanberry不幸的是,Docker人们更愿意不给我们提供平台独立的方式来执行此操作,因为他们更愿意不接受意外的用例(例如从Docker容器访问本地计算机上的任何服务) (2认同)
  • `host.docker.internal` [适用于 Windows 的 Docker](https://docs.docker.com/docker-for-windows/networking/#there-is-no-docker0-bridge-on-windows) ,至少在撰写此评论时。 (2认同)
  • @joanlofe 可悲的是,它不再起作用了。于 19.03.2 测试。 (2认同)
  • 这绝对不行。host.docker.internal 无法解析任何内容。这太复杂了,无法设置,并且无法按照记录进行工作。Docker 版本 20.10.5。 (2认同)
  • `host.docker.internal` 为我工作(Windows 10、WSL2 Ubuntu 20.04、Laravel Sail) (2认同)

Cod*_*der 80

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

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

ipconfig getifaddr en0
Run Code Online (Sandbox Code Playgroud)

这应该会显示当前网络上Mac的IP,并且您的docker容器也应该能够连接到此地址.如果这个IP地址发生变化,这当然是一种痛苦,但你可以在你的Mac上添加一个自定义的环回IP,容器认为它本身不是通过在父机器上做这样的事情:

sudo ifconfig lo0 alias 192.168.46.49
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用telnet在docker容器中测试连接.在我的情况下,我想连接到远程xdebug服务器:

telnet 192.168.46.49 9000
Run Code Online (Sandbox Code Playgroud)

现在,当流量进入您的Mac,寻址为192.168.46.49(并且所有离开您的容器的流量都通过您的Mac),您的Mac将假设IP本身.使用完此IP后,可以删除环回别名,如下所示:

sudo ifconfig lo0 -alias 192.168.46.49
Run Code Online (Sandbox Code Playgroud)

需要注意的一件事是,如果docker容器认为流量的目的地本身就不会向父主机发送流量.如果遇到问题,请检查容器内的loopback接口:

sudo ip addr show lo
Run Code Online (Sandbox Code Playgroud)

就我而言,这表明inet 127.0.0.1/8我无法使用该127.*范围内的任何IP .这就是我192.168.*在上面的例子中使用的原因.确保您使用的IP与您自己网络上的某些内容不冲突.

  • 这个主机名的使用没有意义,因为它不能在 Docker for Linux 下工作。为什么他们没有为 Linux 添加它? (2认同)

Nat*_*Fox 42

对于在AWS中运行Docker的用户,仍可从容器内部获取主机的实例元数据.

curl http://169.254.169.254/latest/meta-data/local-ipv4
Run Code Online (Sandbox Code Playgroud)

例如:

$ 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
Run Code Online (Sandbox Code Playgroud)


小智 42

docker network inspect bridge -f '{{range .IPAM.Config}}{{.Gateway}}{{end}}'
Run Code Online (Sandbox Code Playgroud)

可以使用 docker 网络检查 来检索它

  • 到目前为止的最佳答案是考虑到它不依赖于容器中存在的任何二进制文件。 (4认同)

Nek*_*Nek 37

AFAIK,在 Docker for Linux(标准发行版)的情况下,主机的 IP 地址将始终是 172.17.0.1(在 docker 的主网络上,请参阅评论以了解更多信息)。

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

ifconfig
Run Code Online (Sandbox Code Playgroud)

在 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"
Run Code Online (Sandbox Code Playgroud)

  • 对于附加到“docker0”默认桥接接口的容器来说也是如此。使用 Docker Compose 建立的容器并非如此,它不会存在于默认的桥接口上。`docker network ls` 和 `docker network inform <network_name>` 可以帮助您找出该 IP 是什么。 (5认同)
  • 感谢您的指示。顺便说一句,我在 Linux 上,我期望 172.17.0.1,事实上我正在检查一个容器,它有 172.23.0.1。正在运行的容器数量是否会影响通过增加 ip 编号来映射主机的方式? (2认同)
  • @funder7这实际上取决于你在docker中使用的网络。您可以使用“docker network ls”访问网络,如果您没有定义任何网络,只需知道 docker-compose 在 docker 内自动定义的虚拟网络(您也可以列出)。 (2认同)

Mag*_*res 22

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

run --env <key>=<value>
Run Code Online (Sandbox Code Playgroud)

  • 更具体地说,桥接IP地址可以使用命令行选项传递,如:`-e"DOCKER_HOST = $(ip -4 addr show docker0 | grep -Po'inet\K [\ d.] +')"` (使用http://unix.stackexchange.com/questions/87468/is-there-an-easy-way-to-programmatically-extract-ip-address中接受的答案) (16认同)
  • 我认为它不适用于Docker for Mac/Windows.(桥IP) (7认同)

ma-*_*ick 21

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

docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print  $3}'` [my container]
Run Code Online (Sandbox Code Playgroud)

(来自/sf/answers/1880539811/)


BMi*_*tch 18

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

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


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

如果你的容器是用主机网络运行的,那么你可以直接查看主机上的路由表,查看默认路由出来。从这个问题以下对我有用,例如:

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

使用容器中的主机网络显示这一点的示例如下所示:

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

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

getent hosts host.docker.internal | awk '{print $1}'
Run Code Online (Sandbox Code Playgroud)

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

docker run --add-host host.docker.internal:host-gateway ...
Run Code Online (Sandbox Code Playgroud)

如果您在云环境中运行,您可以检查来自云提供商的元数据服务,例如 AWS 服务:

curl http://169.254.169.254/latest/meta-data/local-ipv4
Run Code Online (Sandbox Code Playgroud)

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

curl ifconfig.co
Run Code Online (Sandbox Code Playgroud)

这些中的每一个都有局限性,并且仅适用于特定场景。最可移植的选项仍然是运行您的容器,将 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
Run Code Online (Sandbox Code Playgroud)


Nic*_*aly 13

适用于 Mac 和 Windows 的 TLDR

docker run -it --rm alpine nslookup host.docker.internal
Run Code Online (Sandbox Code Playgroud)

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

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

Name:      host.docker.internal
Address 1: 192.168.65.2
Run Code Online (Sandbox Code Playgroud)

细节

MacWindows 上,您可以使用特殊的 DNS 名称host.docker.internal

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


yam*_*ami 8

如果您想要真正的IP地址(而不是桥接IP)Windows并且您有docker 18.03(或更近期),请执行以下操作:

从映像名称为nginx(处理Alpine Linux distribution)的主机运行容器上的bash :

 docker run -it nginx /bin/ash
Run Code Online (Sandbox Code Playgroud)

然后在容器内运行

/ # nslookup host.docker.internal

Name:      host.docker.internal
Address 1: 192.168.65.2
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 我试过你的解决方案,似乎找不到 nslookup 命令 (2认同)

ily*_*ect 7

我有 Ubuntu 16.03。为了我

docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print  $3}'` [image]
Run Code Online (Sandbox Code Playgroud)

工作(错误的IP被生成)

我的工作解决方案是:

docker run --add-host dockerhost:`docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge` [image]
Run Code Online (Sandbox Code Playgroud)


BSC*_*hir 6

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


PCa*_*Cas 5

如果您启用了docker远程API(例如通过)并知道主机的主机名或IP地址,则可以使用大量bash来完成.-Htcp://0.0.0.0:4243

在我的容器的用户中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'
)
Run Code Online (Sandbox Code Playgroud)

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

第三行卷曲到主机(假设你使用4243作为docker的端口)然后使用node来解析返回的JSON DESIRED_PORT.


Are*_*ani 5

在linux中你可以运行

HOST_IP=`hostname -I | awk '{print $1}'`
Run Code Online (Sandbox Code Playgroud)

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

HOST_IP=`docker run busybox ping -c 1 docker.for.mac.localhost | awk 'FNR==2 {print $4}' | sed s'/.$//'`
Run Code Online (Sandbox Code Playgroud)

  • 第一个代码块将获取容器IP而不是主机IP (3认同)
  • `hostname -I` 的 mandoc 警告不要“对输出的顺序做出任何假设”。 (2认同)

Din*_*ray 5

我的解决方案:

docker run --net=主机

然后在docker容器中:

主机名-I | awk '{打印$1}'