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

时间:2014-04-08 17:53:32

标签: docker ip

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

26 个答案:

答案 0 :(得分:270)

/sbin/ip route|awk '/default/ { print $3 }'

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

答案 1 :(得分:119)

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

注意,如documentation中所示,"这是用于开发目的[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

在我的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

答案 2 :(得分:78)

更新:在适用于Mac的Docker 上,从版本18.03开始,您可以使用 host.docker.internal 作为主机的IP。见allanberry'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与您自己网络上的内容不冲突。

答案 3 :(得分:39)

对于那些在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

答案 4 :(得分:23)

AFAIK,对于适用于Linux的Docker(标准发行版),主机的IP地址将始终为 172.17.0.1(在Docker的主要网络上,请参阅注释以了解信息)更多)。

最简单的方法是从主机通过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"

答案 5 :(得分:22)

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

run --env <key>=<value>

答案 6 :(得分:20)

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

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

(来自https://stackoverflow.com/a/26864854/127400

答案 7 :(得分:7)

如果您想在IP上使用真实的IP地址(而不是网桥Windows),并且您有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地址正在更改(如果没有网络访问权限,则没有IP地址)。从18.03开始,我们的建议是连接到特殊的DNS名称host.docker.internal,它将解析为主机使用的内部IP地址。这是出于开发目的,不适用于Docker for Windows以外的生产环境。

答案 8 :(得分:6)

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

主机具有更改的IP地址(如果您没有网络访问权限,则为无)。从18.03开始,我们建议连接到特殊DNS名称host.docker.internal,该名称解析为主机使用的内部IP地址。

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

答案 9 :(得分:5)

如果您启用了docker remote API(例如通过-H tcp://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&#39; s端口)然后使用node解析DESIRED_PORT的返回JSON。

答案 10 :(得分:4)

适用于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

详细信息

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

  

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

答案 11 :(得分:2)

在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'/.$//'`

答案 12 :(得分:2)

这是在AWS中运行Docker的人的另一个选项。此选项可避免使用apk添加curl包并节省宝贵的7mb空间。使用内置的wget(单片BusyBox二进制文件的一部分):

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

答案 13 :(得分:1)

对于大多数希望自动执行此操作的应用程序,标准的最佳实践是:您不这样做。取而代之的是让运行容器的人员注入外部主机名/ IP地址作为配置,例如作为环境变量或配置文件。允许用户注入它可以为您提供最便携的设计。

为什么这么难?因为容器将通过设计将应用程序与主机环境隔离。默认情况下,网络仅以该容器的名称空间命名,并且主机的详细信息不受容器内部运行的进程的保护,该进程可能不会得到完全信任。


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

如果您的容器通过主机网络运行,则可以直接查看主机上的路由表以查看默认路由,例如:

ip r s 0/0 | awk '{print $3}

通过容器中的主机网络进行显示的示例如下:

docker run --rm --net host busybox /bin/sh -c "ip r s 0/0 | awk '{print \$3}'"

对于某些版本的Docker Desktop,他们注入了DNS条目:

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

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

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

如果您需要外部/互联网地址,则可以查询以下远程服务:

curl ifconfig.co

每一个都有局限性,仅在特定情况下有效。最可移植的选择仍然是使用注入的IP地址作为配置来运行容器,例如这是在主机上运行较早的ip命令并将其作为环境变量注入的选项:

docker run --rm -e HOST_IP=$(ip r s 0/0 | awk '{print $3}') busybox printenv HOST_IP

答案 14 :(得分:1)

docker network inspect bridge -f '{{range .IPAM.Config}}{{.Gateway}}{{end}}'

可以使用 docker network inspect 来检索它

答案 15 :(得分:1)

因此...如果您使用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/

答案 16 :(得分:1)

尝试一下:

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

答案 17 :(得分:0)

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

  • -i--ip-address地址作为主机名
  • -I--all-ip-addresses主机的所有地址

例如:

$ hostname -i
172.17.0.2

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

IP=$(hostname -i)

答案 18 :(得分:0)

这是 Node.js 中的一种简约实现,该对象使用上述EC2 Metadata instance

在谁在 AWS EC2实例上运行主机。
ec2(function(err, ip) {
        if(err) console.log(err)
        else console.log(ip);
    })

并用作

dict

答案 19 :(得分:0)

我有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}}{{.Gateway}}{{end}}' bridge` [image]

答案 20 :(得分:0)

我使用的解决方案基于一个“服务器”,该服务器在收到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上运行,泊坞窗主机的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

答案 21 :(得分:0)

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

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

答案 22 :(得分:0)

这是我的方法。在这种情况下,它将主机条目添加到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容器的本地计算机。

答案 23 :(得分:0)

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

答案 24 :(得分:0)

我的解决方案:

docker run --net=host

然后在 docker 容器中:

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

答案 25 :(得分:-5)

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