如标题所示。我需要能够检索Docker主机的IP地址和从主机到容器的端口映射,并在容器内部进行操作。

评论

您能否详细说明如何使用此信息?您说“ Docker主机”-您是否在多个主机上运行Docker?一旦您的容器知道主机和端口映射的IP地址,它将做什么?

将docker主机IP地址传递到docker容器的最简单方法是,我认为您应该使用“ docker container exec”在容器内进行调用。假设您要从busybox容器内部ping主机,请使用:$ IP ='8.8.8.8'&& docker container busybox ping $ IP'查找主机IP的方法,请使用更多您喜欢的主机。

#1 楼

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


@MichaelNeale注意到,没有必要在Dockerfile中使用此方法(除非仅在构建时需要此IP),因为此IP将在构建时进行硬编码。 >

评论


当您对容器使用docker网桥(默认)时,这将输出网桥IP(如172.17.42.1),而不是主机的IP(如192.168.1.x)(我假设您的主机位于本地NAT上)。如果您需要192.168.1.x地址,在这种情况下使用@Magno Torres答案可能是人们想要的。

–Programster
2014-09-18 11:10



RUN将无法按您预期的那样工作-它只会在构建时计算IP-此后将永远是静态的,并且没有用。这将是构建主机的IP。

–迈克尔·尼尔(Michael Neale)
15年3月3日在7:14

@Programster,我可以假设人们想要docker主机和容器之间的连接,这就是网桥IP可以为您提供的(当然是在stndard“ home”安装中)。如果有人甚至可以在docker bridge之外并且无法访问,为什么有人需要“真实的”主机IP?这是所有刚安装docker并希望在短时间内使用它的人的解决方案。

–棘
2015年3月4日,下午2:56

@MichaelNeale,像以前一样,我假设大多数以Docker开头的人都需要主机和容器之间的连接,就是这样。如果有人在进行“适当的”部署,则可能无论如何他都没有使用docker bridge,而是在使用自定义网络,并且可能他知道所有网络怪癖,或者他们已经设置了DNS(或任何发现)。

–棘
2015年3月4日在2:59



@spinus-但这仅在它在其构建的主机上运行时才有效-在这种情况下-您可以对其进行硬编码-或查找-我认为这不是有用的答案,并且会误导很多人人-建议您将其删除。 (RUN位)

–迈克尔·尼尔(Michael Neale)
2015年3月6日,0:28

#2 楼

从18.03版开始,您可以将host.docker.internal用作主机的IP。
可在Mac版Docker,Windows版Docker以及其他平台上使用。
这是Mac专用docker.for.mac.localhost的更新,
请注意,如Mac和Windows文档中所述,仅用于开发目的。
例如,自17.06版开始提供,并且自17.12版以来提供的docker.for.mac.host.internal也可以在该平台上使用。我在主机上设置了环境变量:
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容器访问本地计算机上的任何服务)

–安迪
18年1月16日在4:00

我被介绍给Docker就像一次构建它,到处运行它。但这是完全错误的,因为您还必须同时配置主机系统。因此docker.for.mac ..是没有用的,因为在大多数情况下,您公司中没有Linux或Mac专用环境。混合使用,您有使用Linux,Mac和Windows的开发人员。该域毫无意义,因为在99%的环境中,它是一个混合的Host OS环境。我没有在macOS下开发容器并将其部署到macOS服务器。我将其部署到Linux。这就是每个人都在做的。那么,甚至docker.for.mac ..的重点是什么?

–TheFox
18年3月16日在16:08



@allanberry docker.for.mac.host.internal无关紧要,无论您使用的是带docker-compose还是不带docker-compose的Docker。我想在配置文件中使用固定主机。 IDK,例如docker.host.internal,它始终指向主机IP地址。不管我使用哪个主机系统。这就是使用Docker的全部要点:我想自治。我知道这在macOS上更加棘手,因为在主机系统和容器之间还有另一层。但是无论如何,我认为docker.for.mac.host.internal只能在macOS上使用而没有用。

–TheFox
18年3月16日在18:03

host.docker.internal也在Windows的Docker上也可以使用,至少在撰写此评论时。

– joanlofe
19年4月4日在8:27



@joanlofe不幸的是,它不再起作用了。在19.03.2。测试

– KMC
19/09/12在17:18



#3 楼

更新:在Mac版Docker(版本18.03)上,您可以使用host.docker.internal作为主机的IP。请参阅allanberry的答案。对于Mac的较早版本的Docker,以下答案可能仍然有用:

在Mac的Docker上,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。使用完该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与您自己网络中的IP不冲突。

评论


使用此主机名没有任何意义,因为它在Linux的Docker下不起作用。他们为什么不为Linux也添加它?

–TheFox
18年8月28日在9:49

他们此时正在@TheFox进行调查:github.com/docker/libnetwork/pull/2348

–伊沃·佩雷拉(Ivo Pereira)
19/12/17在12:51

#4 楼

对于在AWS中运行Docker的用户,仍可以从容器内部访问主机的实例元数据。

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中部署容器),这是理想的选择。

–理查德·克莱顿(Richard Clayton)
16年7月11日在20:41



这是一个救命稻草,谢谢。我在弄清楚如何处理ECS集群中容器之间的通信时遇到麻烦。

–布伦南
16 Sep 8'在6:35



在Phusion basimage(基于ubuntu)上,我不得不稍微更改一下命令:ifconfig eth0 | grep -oP'inet \ K \ S +'

– Meuoi
1月26日14:56

如果码头工人有这样的东西会很棒

– Marat Mkhitaryan
11月14日下午16:22

#5 楼

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

run --env <key>=<value>


评论


更具体地说,可以使用以下命令行选项来传递网桥IP地址:-e“ DOCKER_HOST = $(ip -4 addr show docker0 | grep -Po'inet \ K [\ d。] +')”(使用从unix.stackexchange.com/questions/87468/…接受的答案)

– ncoghlan
2015年9月17日上午8:04

我认为它不适用于Mac / Windows的Docker。 (网桥IP)

–zx1986
16年6月29日在16:09

#6 楼

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

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


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

评论


当其他人想要在/ etc / hosts中输入内容时,我说“为此”。在这个问题上,这不是真的。 OP还要求提供“主机和端口图”,而您仅介绍了主机。

–布莱恩(Bryan)
2015年1月18日14:50在

好。我有点困惑,因为可接受的解决方案也只涵盖主机部分。而且我认为您的解决方案优于棘突之一。

–奥古里克
2015年1月19日17:07

如果您想使用dind-docker-in-docker,这将不起作用。内部Docker将具有不同的IP

–嘈杂
15年8月27日在12:55

#7 楼

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"


评论


对于连接到docker0默认网桥接口的容器来说确实如此。使用Docker Compose站起来的容器并非如此,后者不会存在于默认桥接口上。 docker network ls和docker network inspect 可以帮助您确定该IP是什么。

–卡尔·帕特纳德·普兰(Carl Patenaude Poulin)
9月22日13:21

感谢您的指示。顺便说一句,我在Linux上,我期望172.17.0.1,实际上我正在检查一个容器,它的容器为172.23.0.1。通过增加ip数量,正在运行的容器数量可能会影响主机映射的方式吗?

–funder7
10月29日12:04

@ funder7实际上取决于您在docker内部使用的网络。您可以使用docker network ls访问网络,并且如果您未定义任何网络,只需知道docker-docker在docker内部组成自动定义的虚拟网络(您也可以列出)。

–脖子
10月29日15:45

@Nek可能是我的错,我在查看容器的内部ip,而我的docker0网络接口是172.17.0.1,无论如何,我使用了现在支持linux的docker.host.internal。不过感谢您的命令,我将尝试一下!

–funder7
10月30日9:48

#8 楼

对于大多数希望自动执行此操作的应用程序,标准的最佳实践是:您不这样做。取而代之的是让运行容器的人员注入外部主机名/ IP地址作为配置,例如作为环境变量或配置文件。允许用户注入它可以为您提供最便携式的设计。
为什么这么困难?因为容器将通过设计将应用程序与主机环境隔离。默认情况下,网络仅以该容器的名称空间命名,并且主机的详细信息不受容器内部运行的进程的保护,而该进程可能不受完全信任。

根据您的具体情况,有不同的选项:
如果您的容器通过主机网络运行,则可以直接查看主机上的路由表以查看默认路由。从这个问题出发,以下内容适用于我:
ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$//p'

在容器中进行主机联网的示例如下:
docker run --rm --net host busybox /bin/sh -c \
  "ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$//p'"

对于当前版本的Docker Desktop,他们注入了在嵌入式VM中的DNS条目:
getent hosts host.docker.internal | awk '{print }'

在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.]*\) .*$//p')
docker run --rm -e HOST_IP busybox printenv HOST_IP


#9 楼

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


评论


请不要对多个问题添加相同的答案。一旦赢得足够的声誉,就回答最好的一个,并将其余的标记为重复。如果不是重复内容,则针对该帖子量身定制该问题,并标记为不删除。

–巴尔加夫(Bhargav Rao)♦
19年11月7日,下午2:45

#10 楼

如果要在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以外的生产环境。


评论


我尝试了您的解决方案,但似乎找不到nslookup命令

–谢尔盖
18/12/11在12:40

@Sergey您的映像是否基于Alpine Linux?如果没有,请检查您的特定Linux发行版的等效版本。

–卡米尔·维特科夫斯基
18/12/11在14:47



不,我完全使用您的命令-docker run -it nginx / bin / ash

–谢尔盖
18/12/12在22:57

好的-如果您在Windows上,那么我切换到linux容器,而我没有使用Windows容器。您可以通过右键单击docker图标并选择切换到Linux容器来做到这一点。我认为下载图像时可能很重要。如果您有Windows容器,请检查是否删除旧的nginx图像并再次下载它会为您提供另一个容器。如果仍然无法使用-那么您可以尝试在ash中安装nslookup。

–卡米尔·维特科夫斯基
18/12/13在9:04



如果您无法执行nslookup,请执行ping操作。它会显示已解析的IP。对我来说,这个答案有效,而我只是在容器内部使用此主机名(host.docker.internal)

–德米特里·明科夫斯基(Dmitry Minkovsky)
19年5月22日在20:22

#11 楼

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

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

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

#12 楼

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

在容器用户的bashrc中:

export hostIP=$(ip r | awk '/default/{print }')
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的端口),然后使用node解析DESIRED_PORT的返回JSON。

评论


仅在使用端口转发时适用。实际上,HostPort在这里可以是有用的信息,不幸的是,HostIp可能是0.0.0.0

–阿诺特·恩格伦
17年1月6日13:48



#13 楼

我有Ubuntu 16.03。对我来说

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


不起作用(错误的ip正在生成)

我的工作解决方案是:

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


#14 楼

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

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


#15 楼

在Linux中,您可以运行

HOST_IP=`hostname -I | awk '{print }'`


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

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


评论


第一个代码块将获取容器IP而不是主机IP

–阿里
18年8月22日在14:31

主机名的mandoc-我警告不要“对输出顺序做任何假设”。

–cannot_mutably_borrow
19年7月21日在5:13



#16 楼

因此...如果您使用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 -服务/元数据服务/

#17 楼

试试这个:
docker run --rm -i --net=host alpine ifconfig


#18 楼

这是Node.js中的一个简约实现,它使用上述EC2元数据实例在谁在AWS EC2实例上运行主机
 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);
    })
 


#19 楼

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

#20 楼

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

#21 楼

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

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

#22 楼

我使用的解决方案基于一个“服务器”,该服务器在收到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


#23 楼

在Ubuntu上,hostname命令可以与以下选项一起使用:主机名的地址



-i--ip-address地址

-I--all-ip-addresses所有地址用于主机

例如:

$ hostname -i
172.17.0.2


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

IP=$(hostname -i)


评论


这将为您提供Docker容器而不是主机的IP地址

– Mario Camou
2月28日下午16:20

#24 楼

使用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。

–斯潘塞·威廉姆斯
16年11月29日在18:59

这仅适用于在docker-machine上运行的docker。 Mac的新docker无法在docker-machine上运行。

–thomas.han
17年8月10日在5:04