Moby: 记录如何从容器连接到 Docker 主机

创建于 2013-07-05  ·  263评论  ·  资料来源: moby/moby

我在弄清楚如何从容器连接 docker 主机时遇到了一些麻烦。 找不到文档,但确实找到了有关使用172.16.42.1的 irc 日志,这很有效。

如果记录了这种行为以及它与docker0的关系,那就太好了。

最有用的评论

我认为从问题标题中可以清楚地看到要求。 需要有一种简单且有据可查的方式从容器与主机对话,但它已实现。

所有263条评论

当您查看 network.go 内部时,您会发现 docker 会探测未路由的内部网络。

首先 172.16.42.1 被猜测为桥地址,然后是其他地址。

因此,记录这一点不会有太大帮助。 它是您不能依赖的动态方案。

我认为您需要更多的是一种定义用于网桥和客户端的地址的方法。
可以吗?

我认为从问题标题中可以清楚地看到要求。 需要有一种简单且有据可查的方式从容器与主机对话,但它已实现。

+1 有一种连接主机系统的好方法真是太好了

+1,1.0 分支将定义一个自省 API,以便每个容器都可以以范围和受控的方式与主机交互。

目前计划用于 0.8。


@solomonstre
@getdocker

2013 年 8 月 8 日星期四下午 1:10,EJ Bensing [email protected]
写道:

+1 有一种连接主机系统的好方法真是太好了

直接回复此邮件或在 GitHub 上查看:
https://github.com/dotcloud/docker/issues/1143#issuecomment -22351792

那么如何从容器内连接到 docker 主机呢? 我正在尝试通过主机端口而不是容器的私有 IP 连接到 docker 容器。

@gerhard :计划在 0.8 中使用自省 API。 同时,如果你想从容器中访问 Docker API,你可以设置 Docker 监听 Docker 桥的 IP 地址。

为此,您将:

  • 创建一座桥梁

ip link add docker0 type bridge

  • 为其分配一个IP地址

ip link set docker0 up
ip addr add 172.17.0.1/16 dev docker0

  • 启动 docker 并将 API 绑定到网桥

docker -d -H 172.17.0.1:4242

现在您可以从容器中访问 Docker API。

当前(0.7 版)docker 不可靠地支持向其容器之一授予对其自己的控制套接字的无限制访问权限。 此线程中解释的解决方法是不保证有效的黑客攻击,如果它们确实可能随时中断 - 请不要在生产中使用它们或期望我们支持它们。 由于没有可记录的官方功能,因此无法修复此文档问题。

要讨论缺少功能的技巧和解决方法,我建议使用 _docker-user_ 邮件列表或 Freenode 上的 _#docker_ irc 频道。

快乐的黑客

@shykes在这种情况下,是否还有另一个问题可以跟踪此类功能的创建?

顺便说一句,为这样的功能提供动力:这在本地测试服务器(过去我会使用 vagrant)并且我想将容器中的服务器连接到数据库或其他运行的服务器时很有用我的开发机器(docker 主机)。

我已经被这个功能的价值所吸引:)

2013 年 12 月 2 日星期一上午 9:09,Caleb Spare [email protected]
写道:

顺便说一句,为这样的功能提供动力:这在本地测试服务器(过去我会使用 vagrant)并且我想将容器中的服务器连接到数据库或其他运行的服务器时很有用我的开发机器(docker 主机)。

直接回复此邮件或在 GitHub 上查看:
https://github.com/dotcloud/docker/issues/1143#issuecomment -29636528

我在 Fedora 20 上使用 docker 0.7.2,设置Docker UI 。 我必须打开 docker daemon 监听的端口,这样防火墙就不会阻止它:

  • firewall-cmd --permanent --zone=trusted --add-interface=docker0
  • firewall-cmd --permanent --zone=trusted --add-port=4243/tcp

之后 _docker-ui_ 能够连接到 docker daemon 控制套接字。

高温高压
这是对此类功能的明确且合理的需求。

对不起,如果我让一个顽固的线程活着。

这个问题的标题是: “如何从 docker 容器连接到主机”。
我不明白这与docker inspect功能有何关系。 如果我没记错的话,在主机端使用检查功能来查找容器的 IP。

我认为 bkad 的问题是从容器中查找主机 IP。 当然,我不是网络向导,但假设 ip 网关(从容器内部)映射到主机并不是很安全。
(假设没有配置网桥设置或其他东西)。

netstat -nr使用0.0.0.0的网关,我当然可以毫无问题地访问在我的主机上运行的服务器。 我怀疑网关 ip 是静态的(一旦 docker 启动),有人可以确认吗?

另一种方法是使用环境变量将我的主机公共 IP 传递给容器,但公共 IP 可能不是静态的。 虽然主机名在生产中可能会更好地工作,但它们很难在本地使用。

我仍然希望通过环回从 docker 容器调用主机并在主机上显示为127.0.0.1的方法。 或者,如果安全是一个问题,另一个总是具有相同 ip 的环回设备。
或者也许我发现的东西并没有向公众公开我的交流? 就像说我不是网络向导:)
注意,如果使用 ip-gateway 调用 docker host 是“正确的方式”,我们不能记录一下吗?

对于那些希望从容器/proc/net/route中查找网关 ip 的人来说可能是阅读它的正确位置。

此功能的动机包括各种元数据服务。 从 ec2 元数据服务中公开内容会很好。 不适合环境变量的凭据和更复杂的结构化数据的分发。

@jonasfj :实际上有一种更简单的方法,现在 Docker 支持从主机到容器的绑定挂载文件。 您可以绑定安装 Docker 控制套接字,即: docker run -v /var/run/docker.sock:/var/run/docker.sock … ; 这比摆弄网络规则更容易。

我不确定 docker 套接字如何提供帮助。 我仍然认为应该重新打开该问题,没有针对以下情况的文档:

1)在“主机”上,服务在端口 8080 上运行(比如“etcd”)
2) 从该主机启动一个 docker 容器
3)如何从docker容器访问主机上8080端口的服务? URL/IP 是什么?

@jpetazzo如何设置 docker.sock 来解决上述问题?

@vrvolle ,暴露docker.sock并不能解决@bkad 描述的原始问题。
但是会为主机和 docker-container 之间的通信公开一个不同的 unix 域套接字。

例如,如果您想从主机公开 mysql,您将公开 mysql 套接字: /tmp/mysql.sock

或者,如果您像我一样拥有元数据 API,容器应该能够通过该 API 向主机查询各种有用的东西,您可以创建自己的 unix 域套接字并将其公开给容器。 基于 unix 域套接字的 HTTP 应该可以很好地工作。 此外,您没有所有的网络配置问题和安全问题。

只需要阅读'unix domain sockets'。
但:

http://stackoverflow.com/questions/14771172/http-over-af-unix-http-connection-to-unix-socket

声称没有 URL,因此没有普通的客户端可以开箱即用地使用该机制。

另一方面:

http://stackoverflow.com/questions/14771172/http-over-af-unix-http-connection-to-unix-socket

表明以某种方式可以使用这样的套接字。

但我仍然希望能够简单地拥有一个 IP 地址和端口,docker 内的程序可以简单地使用它们。 我将 - 现在 - 使用

 netstat -nr | grep '^0\.0\.0\.0' | awk '{print $2}'

我应该创建一个新问题还是有人可以重新打开这个问题。

@vrvolle
我不是网络人,但我有一些技巧可以通过 unix 套接字将 localhost 代理到容器中,然后在容器代理 unix 套接字内部到容器本地主机(环回设备)......

记录如何做到这一点会很好。 但似乎它不一定是 docker 需要积极支持的功能。

有多种方法可以解决这个问题,具体取决于您想要实现的目标。

如果您想连接到主机上运行的服务(任何类型的服务,例如,将直接在主机上运行的某些 API 或数据库),您必须确定主机的 IP 地址。

一种方法是依靠 Docker 主机可以通过 Docker 网桥的地址访问这一事实,该地址恰好是容器的默认网关。 换句话说,在这种情况下,您可能只需要巧妙地解析ip route ls | grep ^default 。 当然,它依赖于未来可能会改变的实现细节(默认网关恰好是 Docker 主机的 IP 地址)。

另一种方法是使用 Docker API 来检索该信息。 然后,问题变成“如何从容器连接到 Docker API?”,一个潜在的解决方案(被许多容器使用!)是从主机绑定挂载/var/run/docker.sock到容器。 这有一个很大的缺点:API 对容器完全可用,这可能会做坏事。

从长远来看,Docker 将公开一个更好的自省 API,允许访问该信息而不会给容器太多特权。

TL,DR:短期,检查容器的默认路由。 从长远来看,将会有一个很棒的自省 API。

由于暴发户,我也有问题。 我在 /var/run/docker.sock 中找不到任何东西。 并使用命令“-v /etc/run/docker.sock:/etc/run/docker.sock”但什么也没发生。
我认为这是由于内核功能的一些新更新造成的。 请就这个问题给我一个简短的说明。 和完整的命令来解决这个问题。 谢谢

使用 -v /var/run/docker.sock - 而不是 /etc (通常为 conf 文件保留)。

在新的 1.0.0 版本中对此有何更新?

有 nsenter - 但我认为鼓励的方法是在此运行 sshd
阶段。

2014 年 6 月 13 日星期五,Camilo Aguilar [email protected]写道:

在新的 1.0.0 版本中有任何关于此的消息吗?


直接回复此邮件或在 GitHub 上查看
https://github.com/dotcloud/docker/issues/1143#issuecomment -45958769。

迈克尔·D·尼尔
主页: www.michaelneale.net
博客:michaelneale.blogspot.com

vrvolle,谢谢。 很多像我们这样的人都在寻找这样的小花絮

netstat -nr | grep '^0\.0\.0\.0' | awk '{print $2}'

Docker 使用主机 IP 在每个容器上自动更新/etc/hosts ,例如172.17.42.1并调用它例如dockerhost将是一个方便的修复。
我想现在我们被netstat -nr | grep '^0\.0\.0\.0' | awk '{print $2}'困住了

/etc/hosts中为dockerhost +1

+1 为 /etc/hosts 中的 dockerhost,听起来是个好主意

除非专门给出参数或标志,否则永远不要编辑图像中的文件。 此外,并非强制要求 100% 的图像遵循 LSB,因此甚至可能没有/etc目录。 用于包含主机 IP 的文件名也应由命令参数指定。

docker --host /etc/hosts

+1 为 /etc/hosts 中的 dockerhost

+1 为 /ec/hosts 条目

@Sepero docker已经使用链接的容器填充 /etc/hosts ,因此您的论点并不真正成立。

@matleh是的,但我认为正确的方法不是直接填充 /etc/hosts ,或者至少让我们指定位置以防万一我们没有它。

无论如何,主机中的 dockerhost 条目。

我还希望在/etc/hosts中有 docker 主机 IP。

在 /etc/hosts 中的 docker 主机 IP 上 +1

促进访问主机上的网络服务的更好方法可能是简化设置反向转发端口的 iptables 条目,即从容器到主机。 我认为-p--publish选项将由具有相反效果的-s--subscribe选项很好地补充。 不过,我想我会称它们为 --forward 和 --reverse。 不管你怎么称呼它,在我看来,这比这里的其他建议更一致。

这可能是显而易见的,但一种简单的方法是在启动容器之前确定主机上的 ip 地址并在容器中适当地设置环境变量,这种方法目前有效并且可能不太依赖于实现。 沿着这些思路:

#!/bin/bash
HOSTNAME=$(hostname)
HOST_IP=$(ip route | awk '/docker/ { print $NF }')
docker run -e HOST=$HOSTNAME -e HOST_PORT=tcp://$HOST_IP:8000 mycontainer

这基本上与--link的工作方式平行。 它仍然依赖于名称与/docker/匹配的网桥,并且只有一个这样的网桥,但是在启动 docker 守护程序时设置了网桥。 如果docker info能给我们正在使用的网桥的名称和/或主机 IP 地址,那就太好了。 另一个想法是在 $ docker run中添加一个--link-host PORT选项,这基本上可以完成上述操作。

IMO 这是最好的选择。 使用--link-host ,容器不需要知道它正在访问的服务是在主机上还是在另一个容器中。

我不确定其他人是如何调用他们的容器的,但是当我使用--net=host运行它们时,我可以看到与我的 docker 主机相同的网络设置。 如果没有这个开关,我会得到一个独立的网络堆栈,如docker-run手册页中所述。

$ docker run -i --net=host fedora ip route ls
default via 10.0.2.2 dev eth0  metric 1
10.0.2.0/24 dev eth0  proto kernel  scope link  src 10.0.2.15
127.0.0.1 dev lo  scope link
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.42.1
192.168.59.0/24 dev eth1  proto kernel  scope link  src 192.168.59.103

在没有开关的情况下运行会产生以下结果:

$ docker run -i fedora ip route ls
default via 172.17.42.1 dev eth0
172.17.0.0/16 dev eth0  proto kernel  scope link  src 172.17.0.4

我们正在寻找的是一种获取 10.0.2.15(我的 docker 主机的 eth0 i/f 的 IP)或 172.17.42.1(我的 docker 的 docker0 网桥 i/f 的 IP)的 IP 地址的方法。

我并不特别关心将一些主机添加到我的容器 /etc/hosts 文件中的方法,这对我来说似乎有点 hackey。 而是将这些信息在内部公开,以便我可以在需要时获取它,这似乎是更谨慎的方式。

+1 --link-host或其他一些直观的方式

+1 用于 /etc/hosts 条目
看起来很方便,并遵循当前的通信约定。

只是为了澄清我之前的评论: --link <container>:<alias>的优点在于它通过 _alias_ 公开了 _service_。 同样,将主机暴露给容器的机制应该提供对特定服务的访问,而不仅仅是 IP 地址。 容器将通过别名访问该服务; 它不需要知道服务的真正位置。 该选项应该具有-p的反向语义并且行为类似于--link 。 换句话说, --link-host <ip address>:<port>:<alias>将设置环境变量和/etc/hosts条目,并根据需要设置 iptables 条目,即如果主机上的服务正在侦听否则无法访问的 IP 地址到容器。

@altaurog这样的事情怎么样?

docker run --name someservice -d host-exposing-image --expose 8000

someservice将只是您可以--link到的任何名称,而host-exposing-image将是在暴露端口上转发主机端口的特殊图像。 可能通过与图像共享主机的/var/run/docker.sock来实现这个想法。

也许这样的东西已经存在,不知道。

编辑:

docker run --name someservice -d --expose 8000 host-exposing-image

忘记上面的,还没有阅读这里的所有评论(仍然没有)。 这在 docker-osx 上对我有用(很抱歉没有发布到邮件列表中):

docker run --rm -ti -e HOST_IP="$(docker-osx ssh -c 'route -n' 2> /dev/null |
  awk '/^0.0/ { print $2 }')" debian:jessie

+1。 --link-host是一个好主意,并且只需在/etc/hosts中有一个dockerhost条目

由于此问题已关闭(但未解决),因此我创建了一个新问题:#8395

+1 dockerhost或任何其他方便的方式。

+1 任何方便的方式

由于dockerhost方法在这里获得了一些选票,我发现拥有这样一个主机条目的最简单方法(从评论到 3 个相关问题 #8395 #10023)是添加参数--add-host=dockerhost:$(ip route | awk '/docker0/ { print $NF }')运行图像时,例如:

run --add-host=dockerhost:$(ip route | awk '/docker0/ { print $NF }')  ubuntu ping -c2 dockerhost

虽然这添加了所需的 /etc/hosts 条目,但默认情况下不存在dockerhost仍然很遗憾。 分发图像时,我可以选择

  • 指示用户添加上述参数
  • 使一些脚本在容器中运行,根据路由表调整配置文件

我个人不明白为什么dockerhost默认不存在,它会使创建和分发通常在主机(XServer、CUPS、Puleaudio)上访问服务的图像更加方便。

+1 为 dockerhost。 实际上,我会将其公开为 env var、/etc/hosts 条目和 cli 标志。 它一定会以多种方式使用。

:+1: 用于 dockerhost

在您的容器内:

cat << EOF > /etc/profile.d/dockerhost.sh
 grep dockerhost /etc/hosts || echo $(ip r ls | grep ^default | cut -d" " -f3) dockerhost >> /etc/hosts
EOF

每当我登录时都为我工作(使用root帐户)

+1 为 dockerhost

+1 为 dockerhost

+1 为 dockerhost

+1 为 dockerhost

+1 为 dockerhost :yum:

+1 为 dockerhost

+1 为 dockerhost :+1:

写完这个脚本,有人可能会觉得它很有用:

#!/bin/bash

SED="$(which sed)"
NETSTAT="$(which netstat)"
GREP="$(which grep)"
AWK="$(which awk)"
CAT="$(which cat)"


$SED '/dockerhost$/d' /etc/hosts > /etc/hosts.tmp
DOCKERHOST="$($NETSTAT -nr | $GREP '^0\.0\.0\.0' | $AWK '{print $2}')"

echo "$DOCKERHOST dockerhost" >> /etc/hosts.tmp

$CAT /etc/hosts.tmp > /etc/hosts

rm -rf /etc/hosts.tmp

+1 码头主机

由于对这个主题很感兴趣,我认为与其讨论关闭的票证来打开新的功能请求是有意义的。

我前段时间打开了https://github.com/docker/docker/issues/8395 - 也关闭了。 仍然没有记录的解决方案

好的,虽然有解决方法,但我认为主要原因可能是访问主机是一个部分孤立的用例。

由于有一个 docker 链接功能,我认为能够提供到主机的链接是有意义的。

你好!

仅供参考,现在记录在案

注意:有时你需要连接到 Docker 主机,这意味着获取主机的 IP 地址。 您可以使用以下 shell 命令来简化此过程:

$ alias hostip="ip route show 0.0.0.0/0 | grep -Eo 'via \S+' | awk '{ print \$2 }'"
$ docker run --add-host=docker:$(hostip) --rm -it debian

谢谢,@icecrime。

码头工人可以锁定这个问题,以便人们停止更新吗?

+1 为 dockerhost

+1 for dockerhost - 必须运行本地命令别名 hostip 与 docker-compose、docker-swarm 等不兼容。

+1 为 dockerhost

@icecrime ,它提供了主机网关,而不是我的 ubuntu 上的主机 IP。 它不应该只是下面的命令吗?

$ ip address show

+1,无需运行命令即可使用的东西是理想的

这怎么还没有解决? 在容器中运行命令以使容器到主机网络功能是完全不可接受的。

+1 任何简单的东西
顺便说一句, ip的解决方法适用于我的 Ubuntu,但不适用于 OS X,对吗?

+1 这是一个 2 岁的问题和一个有用的功能。 我想要一种从容器内部连接到 docker 远程 api 的简单方法。

@ianchildress如果您的守护程序配置为接受套接字连接,只需将套接字绑定安装到您的容器中,例如docker run -d -v /var/run/docker.sock:/var/run/docker.sock myimage

+1 为 dockerhost
浏览用例解决方案时发现此问题: xdebug.remote_host=dockerhost

+1 为 dockerhost

@thaJeztah ,我如何从那里获取主机名或 IP 地址?

@mbonaci我正在回复@ianchildress ,他想连接到容器内的 Docker API(使用套接字连接是一般方法)

我糊涂了。 上面的@icecrime上面说过,现在已记录在案,但他提供的链接已失效。 我无法快速找到文档的引用部分。 我注意到 apt-cache-ng 示例使用 dockerhost,但没有定义它是什么 (#11556)。 我可以轻松找到的唯一参考是这个线程。 我已经搜索了所有 docker 的源代码和文档,但在这个上下文中似乎没有提到它

@pwaller自 3 月以来,我们已将那份巨大的长文档拆分为单独的参考资料。 此材料的新位置是:

http://docs.docker.com/reference/commandline/run/#adding -entries-to-a-container-hosts-file

+1 为 dockerhost

@moxiegirl我认为--add-host参数令人满意。 谢谢

以及如何从 docker 容器连接到主机? 例如,用于制作 git pull? 没有卷使用?

@a93ushakov这一切都在@moxiegirl提供的链接中进行了解释。
当您执行docker run时,添加以下参数: --add-host=dockerhost:replace_with_docker_host_ip ,这会在容器的/etc/hosts文件中创建一个条目。
当然,这意味着您可以在该容器中使用名称dockerhost来引用您的 docker 主机。

@mbonaci > 当然,这意味着您可以在该容器中使用其名称 dockerhost 来引用您的 docker 主机。

通过ssh?

@thaJeztah > 如果您将守护进程配置为接受套接字连接,...
这个怎么做?

@a93ushakov SSH:如果您在主机上安装并运行它(并且它的端口没有被阻止),是的。

@a93ushakov @thaJeztah指的是 Unix 套接字连接。 我认为这是默认设置 - 看看您的主机上是否有文件/var/run/docker.sock

+1 为 dockerhost

+1 为 dockerhost

+1 为 dockerhost

+1 为 dockerhost
无需任何额外步骤即可获得此主机名会很好。

1 用于 dockerhost

+1 dockerhost

似乎无法从容器内连接到 docker 主机。 任何想法我做错了什么?

$ hostip=$(ip route show 0.0.0.0/0 | grep -Eo 'via \S+' | awk '{ print $2 }')
$ nc -l -p 1234 &
[1] 17361
$ docker run --add-host=docker:$(hostip) --rm -it hiromasaono/curl curl docker:1234
curl: (7) Failed to connect to docker port 1234: Connection refused

+1 为 dockerhost

当我添加 Docker 网桥的 IP 时,它可以工作。

首先用 netcat 监听 1234 端口

$ nc -l -p 1234

获取网桥的 IP

$ ifconfig docker0 | grep 'inet addr'
          inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0

然后连接

$ docker run --add-host=docker:172.17.42.1 --rm -it hiromasaono/curl curl 172.17.42.1:1234

然后我看到回复

GET / HTTP/1.1
User-Agent: curl/7.35.0
Host: 172.17.42.1:1234
Accept: */*

+1 为 dockerhost
见鬼,什么时候?

+1 适用于 Mac 上的 dockerhost,即透明地处理 VM

有人可以告诉我如何从容器内部调用 Docker API 吗? 我不是一个linux人。 我已经用 -v /var/run/docker.sock:/var/run/docker.sock 启动了容器。
大家都在说怎么挂载,但是没有人提到里面怎么调用api。

我尝试使用 curl 调用它不起作用。 我使用了主机IP,例如

curl -XGET http://hostip :2375/images/json

这就是我启动守护进程的方式。 即 docker -H unix:///var/run/docker.sock -H tcp://0.0.0.0 :2375

任何帮助将不胜感激。

@jprogn github 问题跟踪器不适用于一般支持问题; 最好在#docker IRC 频道、Google 上的 docker-users 组或 forums.docker.com 中提出这些问题

这个问题与原始主题有关,尚未完全回答。 请看上面的标题

有人可以回答如何从容器中调用docker api????????????????

@jprogn请按照我上面的评论; 这是一个问题跟踪器,用于跟踪错误和功能请求; 不是使用 docker 的支持论坛; 使用我上面提到的其他方法https://github.com/docker/docker/issues/1143#issuecomment -146924892

+1 为 dockerhost

在我的 CentOS7 docker 主机上,我无法获得从容器到主机的路由:

[root@docker-host-fkb slehmann]# ifconfig docker0 | grep 'inet'

inet 172.17.42.1  netmask 255.255.0.0  broadcast 0.0.0.0
inet6 fe80::42:a7ff:fe4d:4cb2  prefixlen 64  scopeid 0x20<link>


[root@docker-host-fkb slehmann]# docker run --add-host=docker:172.17.42.1 --rm -it hiromasaono/curl curl 172.17.42.1:1234

curl: (7) Failed to connect to 172.17.42.1 port 1234: No route to host

有任何想法吗?

+1,可能应该有一个环境变量。

我自己也希望反过来; 按名称从我的主机到 docker 容器的链接

+1 用于 dockerhost 环境变量

在没有硬编码 172.17.42.1 的情况下组合访问主机的定制 dns 条目真的很棘手。 例如

extra_hosts:
     - "docker:172.17.42.1"

+1 用于 dockerhost 任何地方(ENV 的 /etc/host)

+1 这个还是需要的!

我的 +1 也是因为将ip route list dev eth0 | grep -Eo 'via \S+' | awk '{ print \$2 }'添加到每个项目(因为在开发中,所有项目都在同一个主机中并且需要能够相互调用)开始看起来像是坏黑客

我们如何在集群中解决这个问题,例如 Docker Swarm,我们不知道运行容器时将分配给哪台机器? docker0 网关 IP 可能在 swarm 集群中从一台主机到另一台主机不同,因此我们不能只在一台主机上运行ip route命令,然后假设所有主机的 IP 都相同。

我还希望能够将容器端口映射到 docker0 网桥上的端口,而不必知道 docker0 网桥的 IP 是什么。 像这样的东西:

eval $(docker-machine env --swarm swarm-master-node)
docker run -d -p "$HOST_GATEWAY_IP:80:80" my-image

$HOST_GATEWAY_IP被替换为在容器最终部署到集群中的主机上运行ip route命令所获得的相同 IP。

任何其他涉及 IP 的命令都需要支持这一点,例如 docker run 上的docker run --dns选项。

我发现这个命令更容易:

ip ro | grep docker | sed 's|.* \(\([0-9]\+\(.[0-9]\+\)\{3\}\)\)\s*|\1|'

+1 为 /etc/hosts 中的 dockerhost

+1 码头主机

+1 在 /etc/hosts 中有 dockerhost

+1000 为 dockerhost

+1 码头主机

+1

+1 或更多。

我在一个容器中运行一个 Web 服务器,需要将它连接到我在主机上运行的 mysql。
主机的 ip 随着 dhcp 的变化而变化,所以动态的东西是必须的。

例如, @wederbrand另一种方法(可能性能更好)可能是连接到 mysql 套接字;

docker run -v /var/lib/mysql/mysql.sock:/mysql.sock mywebapp

这将使 MySQL 套接字在容器内作为/mysql.sock可用

@thaJeztah这可能是一个选择。 但是,我正在使用的 docker 映像也用于 mysql 服务器位于远程服务器上的其他环境,并且该映像具有数据库的host:port配置。

我希望我的容器的行为尽可能接近生产中的容器,因此除了设置主机和端口外,不要修改连接属性。

+1

+1

+1

+1

@peterbollen @radek1st @BradRuderman @aldarund @wederbrand @pataiadam @jllado @geniousphp @coreylenertz @dgtlmoon @xlight (仅在 2015 年 12 月就全部+1)
_this_ 问题和 #8395 一样已关闭
我认为在旧问题上添加 +1 不会有帮助。 创建一个新的(我用#8395 做过)或尝试其他一些方法来解决这个问题。

谢谢!

+1

+1 码头主机

+1 为 dockerhost

+1 为 dockerhost

+1 为 dockerhost,来吧...

+1 为 dockerhost

在 swarm 中使用 docker-compose 和缩放 n 元容器自然不会提供一种在所有机器上即时执行节点 IP 地址查找的方法。

如上所述并修改为网关,这不是一个选项:

extra_hosts:
     - "docker:172.18.0.1"

👍 也适用于 dockerhost...

+1 为 dockerhost

+1

+1

+1

+1 码头主机

+1 码头主机

+1 码头主机

+1 为 dockerhost

+1 为 dockerhost

+1 为 dockerhost。
由于此问题已关闭,因此打开了新票。

+1

+1

要在docker-machine设置中获取主机,您可以使用以下命令:

docker-machine ssh "${DOCKER_MACHINE_NAME}" 'echo ${SSH_CONNECTION%% *}'

它会报告您通过ssh连接的机器,因此只要一路上没有 NAT,它对于本地机器和远程机器都应该能正常工作。 如果在技术上可行的话,如果docker-machine inspect也能在某处报告这个值,那就太好了。

+1

+1 为 dockerhost 。 听起来像是一个很有价值的功能,几乎不费吹灰之力就可以实现。

现在,如果您需要在从您控制的图像创建的容器中访问 dockerhost,您可以将此要点添加到您的图像的 entrypoint.sh 脚本中: https ://gist.github.com/dimitrovs/493678fd86c7cdf0c88312d9ddb4906b

或者,如果您的图像不使用 shell 脚本作为其入口点,我想您可以将其添加到 /etc/rc.local 中。 这个要点的作用是检查 /etc/hosts 中的dockerhost ,如果不存在则添加它。 它应该在每次容器启动时发生。

从 /proc/net/route 中获取网关 ip:

export ipaddr=$(printf "%d." $(
  echo $(awk '$2 == "00000000" {print $3}' /proc/net/route) | sed 's/../0x& /g' | tr ' ' '\n' | tac
  ) | sed 's/\.$/\n/')

@dimitrovs你能展示一个示例配置吗? 我对此进行了修补,但无法获得正确的结果。

你得到了什么结果@amcdnl ? 您可以将我链接的要点放在 entrypoint.sh 文件中,以便它在每次容器启动时运行,或者放在容器内的 /etc/rc.local 中。 您必须在构建映像时执行此操作,但脚本本身将在容器启动时执行。

+1 为 docker 主机

@dimitrovs我最终编写了一个脚本,该脚本将在运行时生成一个组合。

启动Docker.sh

#!/bin/bash
built_docker_file="docker-compose.dev.built.yml"

rm -rf docker-compose.dev.built.yml
localhost_ip="$(ifconfig en0 inet | grep "inet " | awk -F'[: ]+' '{ print $2 }')"
sed -e "s/\${localhost}/$localhost_ip/" docker-compose.dev.template.yml > $built_docker_file

docker-compose -f $built_docker_file build
docker-compose -f $built_docker_file up

docker-compose.dev.template.yml

version: '2'

services:
  nginx:
    container_name: sw_nginx
    image: nginx:latest
    ports:
      - 80:80
    links:
     - search
    volumes:
      - ./Web/wwwroot:/var/www/public
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
    extra_hosts:
      - "dockerhost:${localhost}"

@amcdnl很好的解决方法。 请注意, docker-compose支持(环境)变量替换

例如(bash):

$ export localhost=$(...)
$ docker-compose (...)

@sebastiannm我的建议应该独立于主机,因为它在 docker 映像中执行,但是如果您在 VirtualBox 中的 Mac 上运行它,那么您将获得的 IP 是 VirtualBox VM 的 IP,而不是您的 Mac IP。 我认为这是我们正在讨论的要求。 如果您想从 docker 实例中了解 Mac IP,则需要使用不同的方法。

+1 为 dockerhost。

但是现在,我做了一个类似于上面发布的黑客攻击,它允许你使用一个在 Linux 和 OSX 中都可以使用的简单脚本动态获取主机 IP 地址: http ://stackoverflow.com/questions/24319662/from-inside

+1 为 dockerhost。

+1 为 dockerhost

+1+1 码头主机

+1 为 dockerhost

+1 为 dockerhost

+1 为 dockerhost

--net=bridge (默认值)通过本期讨论的各种技术时,我无法从 docker 容器内连接到基本主机 netcat 服务器。

@frankscholten我无法重现您成功的 netcat 测试

我做了一个描述确切问题的stackoverflow问题: http ://stackoverflow.com/questions/38936738/communicate-to-docker-host-from-docker-container
并想在这里发帖以防将来对某人有所帮助

虽然所有这些都是关于在桥接模式下使用 docker0 ip 从容器到主机的通信,但我想知道容器是否也可以与主机的公共 ip(比如它的原始 eth0 ip)通信。 感谢您的回复。 我在这方面没有成功。

@sburnwal我不明白为什么您无法与主机的 eth0 ip 通信。 容器将向其默认网关 (docker0) 发送请求,并且主机应在不进一步转发的情况下进行回复,因为它知道自己拥有该 ip。 您从容器对 eth0 ip 的 ping 是否超时,或者您没有路由到主机或发生了什么? 容器是否能够连接到互联网?

不幸的是,这对我不起作用。 虽然我可以从主机 ping 容器 IP,但我无法从容器 ping 主机(主机的 LAN/eth0)ip。 我正在使用泊坞窗 1.9.1。 我被困在这里,因为我需要我的容器与仅在主机的 eth0 ip 侦听的 Web 服务器进行通信。

我使用以下选项自定义了 docker0:
/bin/docker 守护进程 --bip=169.254.0.254/24 --fixed-cidr=169.254.0.0/24

所以我的主机上有这些接口(这里没有列出 veth* 接口):

[root@pxgrid-106 irf]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtg 1500
        inet 169.254.0.254  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::42:84ff:fe87:d510  prefixlen 64  scopeid 0x20<link>
        ether 02:42:84:87:d5:10  txqueuelen 0  (Ethernet)
        RX packets 512  bytes 150727 (147.1 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 653  bytes 281686 (275.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtg 1500
        inet 172.23.166.176  netmask 255.255.255.128  broadcast 172.23.166.255
        inet6 fe80::20c:29ff:fecc:7d0f  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:cc:7d:0f  txqueuelen 1000  (Ethernet)
        RX packets 58462  bytes 12056152 (11.4 MiB)
        RX errors 0  dropped 69  overruns 0  frame 0
        TX packets 30877  bytes 18335042 (17.4 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

我的容器有 ip 169.254.0.2,我可以从主机 ping 这个容器 ip。 当然,我可以从容器 ping 通它的网关 169.254.0.254(docker0 ip),但我无法 ping 通主机 eth0 ip 172.23.166.176。

我尝试完全停止防火墙,并将这些显式规则添加到 INPUT 链的防火墙中,但还没有运气。 谁能帮我解决这个问题? 或者这是一个错误?

ACCEPT     all  --  172.23.166.176       169.254.0.0/24      
ACCEPT     all  --  169.254.0.0/24       172.23.166.176   

此外,让我在我的主机上也给出 'ip route' 输出:

[root@pxgrid-106 bin]# ip route
default via 172.23.166.129 dev eth0 
169.254.0.0/24 dev docker0  proto kernel  scope link  src 169.254.0.254 
172.23.166.128/25 dev eth0  proto kernel  scope link  src 172.23.166.176 

@tn-osimis 感谢您的建议,我更新并运行良好,这是我的代码供其他人使用:

码头工人-compose.yml

version: '2'

services:
  nginx:
    image: nginx:latest
    ports:
      - 80:80
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
    extra_hosts:
      - "dockerhost:${localhost_ip}"

启动Docker.sh

#!/bin/bash
dev_docker_file="docker-compose.yml"

export localhost_ip="$(ifconfig en0 inet | grep "inet " | awk -F'[: ]+' '{ print $2 }')"

docker-compose -f $dev_docker_file build
docker-compose -f $dev_docker_file up

+1 为 dockerhost

+1 为 dockerhost

+1 为 dockerhost

@magicalbob解决方案确实很神奇🎉

+1 为 dockerhost

+1,顺便问一下,为什么关闭? 问题/功能请求尚未解决

对此有何更新? 什么是正确的方法?

+1

有没有人有关于如何从容器连接到主机(主机的公共 IP,如 eth0 ip 而不是 docker0 接口 ip)的更新?

@sburnwal docker run --add-host=publicip:$(hostname --ip) ubuntu ping -c2 publicip

查看@retog回答

+1 为 dockerhost

+1 为 dockerhost

+1 为 dockerhost

把它留在这里,也许它至少会对你们中的一些人有所帮助:

有人告诉我,默认网络接口并不总是必须是docker0 ,获取docker0 IP 将无法在 linux 以外的系统上运行,这对我们来说是个问题,因为一些我们的开发人员在哪里使用 Mac

因此,我建议不要使用魔法脚本从网络连接中获取主机 IP,而是强制容器的网络设置,而不是尝试以编程方式找出它

我在 docker-compose 文件中配置了 docker 网络设置,如下所示:

``` 网络:
默认:
司机:桥
ipam:
配置:
- 子网:10.10.0.0/24
网关:10.10.0.1

if you are only running one container, you could first create a network (`docker network create`) and connect to it with `docker run --network=<network-name>|<network-id> <image name>`

BUT if you don't want to do this (i.e. force the docker network) and really want to get the default gateway IP, you could get it more cleanly than using `docker0` network interface, for example by parsing the `docker network inspect <network name>`, which outputs the gateway IP (among other things):

...
“IPAM”:{
“驱动程序”:“默认”,
“配置”:[
{
“子网”:“172.17.0.1/16”,
“网关”:“172.17.0.1”
}
]
}
...

you could also use the `--format` option of `docker network inspect` to get only the fields that are of interest, like this:

$ docker network inspect bridge --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}'
$ 172.17.0.1
```

注意:如果有更多.IPAM.Config条目,您将在输出中获得所有条目,因此需要额外的逻辑来选择正确的条目

+1 为 dockerhost

请注意,当您只想在 php-fpm 容器中使用 xdebug 连接到 IDE 进行调试时,这将非常有用,因为您显然无法在容器中运行 IDE。

+1 为 dockerhost

我对上述hackarounds的总结:

docker-compose.yml

nginx:
  restart: always
  build: ./nginx/
  ports:
    - "80:80"
  extra_hosts:
    # requires `export DOCKERHOST="$(ifconfig en0 inet | grep "inet " | awk -F'[: ]+' '{ print $2 }')"` in ~/.bash_profile
    - "dockerhost:$DOCKERHOST"

~/.bash_profile

# see https://github.com/docker/docker/issues/1143
export DOCKERHOST="$(ifconfig en0 inet | grep "inet " | awk -F'[: ]+' '{ print $2 }')"

nginx-conf

location / {
        proxy_pass http://dockerhost:3000;
        proxy_set_header host $host;
        proxy_set_header x-real-ip $remote_addr;
        proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for;
}

我倾向于使用 svendowideit/ambassador docker 镜像来解决这个问题。

例如,如果我想绑定到 Docker 主机上运行的 elasticsearch 节点:

docker run --restart always -d --name elasticsearch --expose 9200 -e ELASTICSEARCH_PORT_9200_TCP=tcp://<host>:9200 svendowideit/ambassador

现在,其他 docker 容器可以通过使用 --link elasticsearch 来查找 elasticsearch,同时不知道 elasticsearch 是否在 docker 容器、主机或任何地方运行。

+1 为 dockerhost

...现在虽然你可以这样做:

$ docker build --build-arg HTTP_PROXY=172.16.42.1 .

...或者在我与docker-compose类似的情况下 - 我这样做:

client:
        build: ./client
        extra_hosts:
            - "foobar:${HTTP_PROXY}"

在构建时设置您的主机:

export HTTP_PROXY=172.16.42.1 && docker-compose build

mac上的@rattrayalex ,我发现这直接打印出IP: ipconfig getifaddr en0

+1 为 dockerhost

你们这些只是为 dockerhost 做 +1 的人,是否可以对现有的相同性质的评论竖起大拇指(反应)? +1 评论只是不必要地扩展/填充此问题线程。 已经有这么多了,不用再补充了,但我们总是可以竖起大拇指! 👍

我认为评论者正在写一个广泛的 +1 来强调这是一个常见的用例,具有已知的解决方法,并且应该需要以小时为单位估计的时间来由 docker 团队编码
还是开了3年了👍

所以,在我看来,这更像是“我们还在这里吗”? 而只是一个表情符号

https://github.com/docker/docker/issues/1143#issuecomment -233152700 中的@magicalbob解决方案在我迄今为止尝试过的每个容器设置和桥接中都能完美运行!

https://github.com/docker/docker/issues/1143#issuecomment -70052272 的解决方案在使用 docker compose extra_hosts时不起作用

+1 为 dockerhost

还是没有dockerhost?

+1 为 dockerhost

+1 为 dockerhost

它不会发生,它在 3 年前就关闭了,他们不打算实施这个。 出于同样的原因 docker.sock 是安全的枪,dockerhost 也是如此。 恕我直言,在您的应用程序内部拥有一个可解析的域名是一个主要的安全问题。 如果必须,只需使用变通方法,选择性地仅在通过 IP 访问主机服务不会增加攻击面的情况下使用。

不要不同意它没有发生,但我不明白 dockerhost 是一个安全风险,除非你也关闭许多简单的解决方法......⁣

从 BlueMail 发送

2016 年 12 月 16 日,17:58,17:58,Paulo Cesar [email protected]写道:

它不会发生,它在 3 年前就关闭了,而且他们不打算这样做
实现这一点。 同样的原因 docker.sock 是安全的枪,
dockerhost 也是如此。 从您的内部拥有一个可解析的域名
应用程序是一个主要的安全问题恕我直言。 如果必须,只需使用
变通方法,仅在无法通过 IP 访问主机服务的情况下有选择地
成为增加的攻击面。

--
你收到这个是因为你被提到了。
直接回复此邮件或在 GitHub 上查看:
https://github.com/docker/docker/issues/1143#issuecomment -267655915

+1 为 dockerhost

+1 为 dockerhost

主机的 IP 是192.168.0.208

docker-compose文件如下:

version: '2'
 services:
   zl-tigervnc:
     image: zl/dl-tigervnc:1.5
     container_name: zl_dl_tigervnc
     restart: always
     tty: true
     ports:
       - "8001:8888"
       - "6001:6006"
       - "8901:5900"
       - "10001:22"
     devices:
       - /dev/nvidia0
     volumes:
       - ~/data:/root/data
       - /var/run/docker.sock:/var/run/docker.sock
     extra_hosts:
       - "dockerhost:192.168.0.208"

此脚本启动了一个容器。 容器想要访问主机上的端口8080 (例如192.168.0.208:8080 )。 但它不起作用。

但是,我使用端口转发将主机上的8080映射到路由器上的8080 。 路由器的 IP 是63.25.20.83 。 容器可以通过端口转发(例如63.25.20.83:8080 )访问主机的8080

我已经从这个页面尝试了许多解决方案,但它仍然不起作用。

请注意,当您只想在 php-fpm 容器中使用 xdebug 时,这将非常有用
连接到您的 IDE 进行调试,因为您显然无法在容器中运行 IDE。

正是@colinmollenhour ! 除了有一个额外的问题。 您可以 ping 主机,但实际上无法连接到主机的端口(例如,在 9000 上运行的远程调试器)。

网上有很多旧的和/或不太正确的东西。 很多人似乎认为设置别名 IP 并将其附加到 lo 接口应该可以工作,但事实并非如此。

(在主机上使用 netcat 进行测试,在 docker 容器中使用 telnet 进行测试,所以我已经很好地剥离了)。

@bitwombat检查您主机的防火墙以获取端口 9000 规则

@gregmartyn就是这样。 谢谢! 本来是我在更简单的设置中检查的第一件事! 所有的欺骗层都让我检查了更奇怪的东西。

2013 年 7 月到 2017 年。快 4 年了,这怎么还没有功能? 这显然不是一个孤立的用例。

这不是一个特性,因为它不符合 Docker 成为多主机部署管理解决方案的战略。

我仍然相信有许多有效的用例,添加该功能不会对 Docker 的策略造成任何损害。 无论如何,这是一个从容器中解析 docker 主机地址的简单解决方案,我认为它应该可以通用:

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

+1 dockerhost

非常需要。 +1 dockerhost

+1 dockerhost

+1 为 dockerhost

+1 为 dockerhost

+1 对于任何不是 hacky 解决方法的解决方案。 这里没有任何作用。

同意。 +1 的解决方案。 需要它来对使用 docker 的项目进行开发和测试工作。

+1 为 dockerhost

+1 为 dockerhost

+1 为 dockerhost

哇.. 4 年,而且越来越强大。 为dockerhost +1?

+1 码头主机!!

+1 码头主机!!!

这可能是静音。 我们也许应该提出一个新问题来引用这个问题。

:+1: 对于 dockerhost... 现在我正在通过 env 进行设置:

export DOCKERHOST=$(ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1)

它使事情变得麻烦。

即使像在具有 ssh-tunneled 私有注册表的容器中使用 docker-compose 这样简单的事情也不起作用,因为 Docker 对不想要 dockerhost 如此死心塌地。

注意:此问题已关闭,因此没有必要添加更多评论 :-)

如果您需要此功能,您可以使用--add-host和等效选项轻松添加dockerhost DNS 别名。

为什么默认情况下不可用? 因为它只适用于琐碎的情况。 IE:

  • _不_具有网络访问权限的容器呢?
  • 拥有 _multiple_ 网络的容器呢?
  • 运行在 Swarm 集群上的容器呢?

如果您有一个很好的用例(即“我想做 XXX,并且这样做,我想要dockerhost ...”)以及对上述问题的可靠答案(以及其他可能出现的极端情况),请随意打开一个新问题来引用这个问题!

谢谢你。

问题是您的主机 IP 可能是动态的,具体取决于您所在的网络。 如果您正在开发连接到主机进行调试是必须的。 每个人都想要 dockerhost 的原因不是因为不存在的选项根本不方便或有用。
Docker 有很多与所有人都不相关的选项,这有什么不同? 如果需要,为什么不在 docker 中启用 dockerhost 选项,我猜这会让 99% 的人感到高兴。

@jpetazzo

没有网络访问权限的容器呢?

然后 dockerhost 将无法工作。

有多个网络的容器呢?

然后 dockerhost 将无法工作。

运行在 Swarm 集群上的容器呢?

谁在乎?

如果您正在开发一些涉及 docker 生态系统之外的组件的软件(例如在主机上的 Windows VM 中运行的一些软件),那么将其连接到 docker 会很痛苦。 为什么一定要痛?

您列出的所有案例都不是该线程中的 226 条评论所谈论的,它们是在谈论基本案例。

编辑:对不起,我已经删除了我的部分评论。 我不是故意吐槽的。 这有点令人沮丧,这对于 docker 的某些用户来说是一个非常需要的功能,如果您正在开发需要它的软件,那么似乎无缘无故地绕过它更加令人沮丧。

@jpetazzo有时“琐碎”的案例占用例的 80%。 Dockerhost 对于在开发或暂存环境中使用 Docker的人来说非常有价值,或者实际上任何不依赖 swarm / 多主机网络的环境。 以下是我想使用 Dockerhost 的一些示例:

1) 带有私有注册表的 Windows 上的Docker-Compose 。 我们有一个自托管的私有 Docker 注册表。 开发人员可以通过带有端口转发的 SSH 隧道访问注册表(即在 localhost:5000 上)。 但是当 Docker-Compose 在自己的 Docker 容器中运行时,无法指定私有注册表主机。 如果我们有 dockerhost ,我们可以在 docker-compose.yml 文件中使用 d ockerhost:5000 ,让它访问主机上的转发端口。

2) 任何需要与主机上运行的服务通信的应用程序。 例如,如果存在 dockerhost ,则可以使用在 docker容器中运行的基于 Web 的 SSH 客户端与主机建立 SSH 连接。 如果有 dockerhost ,可以使用在 Docker 容器主机上运行的服务的无数示例。

3) 反向端口转发。 我们可以让我们的 SSH 或 OpenVPN 服务器在 Docker 容器中运行,如果有 dockerhost ,它可以让客户端访问在主机上运行的服务。 您可以设置从容器到 dockerhost 的端口转发。

我很想听听任何技术上的理由,为什么 Moby 开发人员在 dockerhost 方面拒绝听取社区的意见。 到目前为止,我只听到政治/商业原因。

在试图找到一种将 macvlan 网络接口附加到 swarm 服务的方法时遇到了这个线程...... Swarm 似乎是一个半成品的解决方案,无法将服务直接暴露给外界对我来说是一种持续的挫败感。 感觉 Docker 在现实世界的用例中失去了吸引力,从这个线程开始快进 4 年,仍然没有本地实现来让容器自己管理。

我对 Docker 比较陌生。 我从官方文档中读到的一切都是有道理的。 _Docker实际上是一个相当容易上手的工具。_

事实上,我花了几个小时试图弄清楚的唯一一件事是_如何从容器内连接到主机。_其他一切都很容易确定。 我仍然不知道该怎么做。 这个论坛和 SO 上的很多“黑客”都不起作用。 我们需要访问主机以使用一个已经好几个月没有设置为“Dockerized”的遗留应用程序。

恐怕永远不会发生,乔希。 开发人员已经明确表示了这一点。
这使得 docker 对于一大类应用程序来说比无用更糟糕,
不幸的是,码头工人(或“白鲸”)不能对那些折腾
开发人员或那些应用程序。

2017 年 6 月 19 日 01:08,“Josh Wedekind” [email protected]写道:

我对 Docker 比较陌生。 我从官方文档中读到的所有内容
说得通。 Docker 实际上是一个相当容易上手的工具。

事实上,我花了几个小时试图弄清楚的唯一一件事
如何从容器内连接到主机。 其他一切
很容易确定。 我仍然不知道该怎么做。 很多的
这个论坛和 SO 上的“黑客”是行不通的。 我们需要访问
主机以使用未设置为“Dockerized”的旧版应用程序
好几个月。


您收到此消息是因为您发表了评论。
直接回复此邮件,在 GitHub 上查看
https://github.com/moby/moby/issues/1143#issuecomment-309311997或静音
线程
https://github.com/notifications/unsubscribe-auth/AA-shyjglsJXawxHHWGhQH0d1LlZeJqxks5sFbwXgaJpZM4Ayw00
.

您可以使用简单的声明性 docker-compose 文件来处理所有情况,这确实令人沮丧,但是您应该使用一千个技巧从开发环境中的容器连接到遗留应用程序。
@thaJeztah对 docker 的第一印象并不好。

仅供参考,正是出于这个原因,我们最终在生产中放弃了 Docker。 我知道 Docker 开发人员坚决反对它(我知道它并不像某些人声称的那样微不足道),但我只是想插话:由于顽固地拒绝考虑,你正在失去现实世界的客户这个问题。 作为我公司的一个不情愿的 Docker “专家”,我现在不得不提醒那些问我这件事的人说“Docker 很棒......除非你需要与 localhost 上运行的任何东西进行通信。”

所以,再一次,我确信这个问题已经解决了,但是如果你回头看看这个线程,Docker 开发人员,这会造成真正的痛苦,并导致真正的 Docker 客户停止使用 Docker。 我建议重新考虑你顽固地拒绝解决这个问题; 仅仅因为它不符合对“应该”如何使用 Docker 的看法并不意味着它是一个无用或不必要的功能。

他们不仅会失去现有客户。 如果它兑现了开发的承诺,我们本可以将所有东西迁移到 docker。 这对于 docker 大规模用于所有进程来说是真正的反推广。

我现在让它工作的方法是创建一个网络。 这是我的 docker-compose 文件的样子:

version: '2'
services:
  <container_name>:
    image: <image_name>
    networks:
      - dockernet

networks:
  dockernet:
    driver: bridge
    ipam:
      config:
        - subnet: 192.168.0.0/24
          gateway: 192.168.0.1

完成此操作后,您可以使用 192.168.0.1 访问主机。
可能对你们中的某些人有用,因为此功能不会很快推出。

@deltabweb进入主机应用程序的请求会显示为“localhost”流量,还是我必须修改应用程序以响应 192.168.0.1?

谢谢你的帮助。

@halfnibble
我没有详细查看networks的文档,但我的理解是在您的主机上创建了一个新网络,其中:

  • “dockerhost”的 IP 是 192.168.0.1
  • 第一个容器的IP是192.168.0.2
  • 第二个容器的 IP 是 192.168.0.3
  • 等等 ...

从那里开始,一切都应该像在本地网络上连接物理机器一样工作:

  • 机器可以相互连接
  • 你甚至应该能够从主机使用ping 192.168.0.2 - 这只有在你的容器响应 ping 时才有效。

因此,要回答您的问题,我认为您在主机上的应用程序需要响应 192.168.0.X(取决于尝试连接的容器)。

@deltabweb云我如何访问服务器主机端口? >>> 连接被拒绝

@nooperpudd只是为了确定:您正在尝试从容器访问在主机上运行的应用程序,对吗?
我将首先检查应用程序是否允许来自外部的传入连接(0.0.0.0 而不仅仅是 localhost)。 也许还要确保您没有阻止连接的防火墙?

@nooperpudd如果你使用Docker for mac你不能使用host模式, @deltabweb解决方案也不适合我(我的服务器都在监听0.0.0.0和我的主机防火墙被关闭但我每次都得到Connection refused )。 经过大约 2 天的尝试和错误,我发现解决此问题的唯一方法是下面的脚本:

#!/bin/bash
export DOCKERHOST=$(ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1)

# You should use DOCKERHOST env variable in your `docker-compose.yml` 
# and put it everywhere you want to connect to `localhost` of the host machine
docker-compose $@

这种方法的唯一问题是如果您的 IP 在运行容器后发生更改,您应该再次运行它们并且它们找不到您的新 IP。

对我来说,一个值得注意的观察是,在启动 docker 容器时执行的命令无法通过其主机 IP 地址连接到容器。 但是,当该命令未执行此类连接尝试并成功完成执行时,容器便能够通过其主机 IP 地址访问自身。

在尝试将 NoSql 数据库集群实例的端点暴露给 swarm 集群外部的客户端时,我做了这个观察。 毕竟,这些端点需要配置虚拟机的私有或公共 IP 地址,以便外部客户端访问它们。 然而,Cassandra 的设计方式是在启动时尝试立即连接主机 IP 地址(设置为CASSANDRA_BROADCAST_ADDRESS环境变量——见下文),因此失败。 另一方面,Mongodb的replicasets节点首先都是以clean状态启动,然后执行单独的initiating命令,使primary和secondary节点形成replicaset。

下面你会看到对 cassandra 的观察的详细说明(我使用 docker swarm 创建了这些,但同样的问题出现在docker run -d中(在 NAT 模式下,因此没有 --net=host 选项)

1) 一方面,一个容器由

docker service create  --name cassandra-service
--publish mode=host,target=7000,published=7000,protocol=tcp 
-e CASSANDRA_SEEDS=host IP address  -e CASSANDRA_BROADCAST_ADDRESS=host IP address

失败并显示无法连接到监听地址的消息: <host IP address>:7000

2) 另一方面,连接到覆盖网络的容器,由

docker service create  --network cassandra-net --name cassandra-service
-e CASSANDRA_SEEDS=cassandra-service  -e CASSANDRA_BROADCAST_ADDRESS=cassandra-service

正确启动,同时我可以连接到cassandra:2.0映像的 Dockerfile 中公开的任何端口上的主机 IP 地址:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                                         NAMES
07603a75a379        cassandra:2.0       "/docker-entrypoin..."   About a minute ago   Up About a minute   7000-7001/tcp, 7199/tcp, 9042/tcp, 9160/tcp   cassandra-service-1.1.m243u97zku15w08m6puytdngs

$ docker exec -it 1e61ec16f8d0 bash
root<strong i="5">@1e61ec16f8d0</strong>:/# cqlsh 172.17.13.151
Connected to Test Cluster at 172.17.13.151:9160.
[cqlsh 4.1.1 | Cassandra 2.0.17 | CQL spec 3.1.1 | Thrift protocol 19.39.0]

同样,在创建第二个 cassandra 节点期间也可以观察到相同的情况

1)如果我在另一个节点上创建第二个 cassandra 容器

docker service create  --network cassandra-net --name cassandra-service-2
-e CASSANDRA_SEEDS=172.17.13.151  -e CASSANDRA_BROADCAST_ADDRESS=cassandra-service-2

容器因运行时异常而失败,它无法与种子八卦:

java.lang.RuntimeException: Unable to gossip with any seeds
        at org.apache.cassandra.gms.Gossiper.doShadowRound(Gossiper.java:1322)
        at org.apache.cassandra.service.StorageService.checkForEndpointCollision(StorageService.java:457)

2)另一方面,如果我通过docker run -d创建一个 cassandra 容器,我可以通过其主机 IP 地址访问种子节点:

$ docker run -d cassandra:2.0
d87a79cc3de8cd7e4cf40284d1eca91ceb660581cc71082fe64a6b84a09fbd77
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                         NAMES
d87a79cc3de8        cassandra:2.0       "/docker-entrypoin..."   3 seconds ago       Up 2 seconds        7000-7001/tcp, 7199/tcp, 9042/tcp, 9160/tcp   trusting_ardinghelli
$ docker exec -it d87a79cc3de8 bash
root<strong i="17">@d87a79cc3de8</strong>:/# cqlsh 172.17.13.151
Connected to Test Cluster at 172.17.13.151:9160.
[cqlsh 4.1.1 | Cassandra 2.0.17 | CQL spec 3.1.1 | Thrift protocol 19.39.0]
Use HELP for help.
cqlsh>

特别是对于 Cassandra,您可以通过关闭 cassandra 节点的自动引导来解决此问题。 您可以通过使用 Compose V3 中的入口点命令在/etc/cassandra/cassandra.yaml $ 中将 $ auto_bootstrap设置为false $ 来做到这一点:

version: '3'
services:
  cassandra-1:
    image: cassandra:2.0
    entrypoint:
    - "sh"
    - "-c"
    - "echo auto_bootstrap: false >> /etc/cassandra/cassandra.yaml; /docker-entrypoint.sh cassandra -f"
    environment:
      CASSANDRA_BROADCAST_ADDRESS: 172.17.13.151
    volumes:
    - volume1:/var/lib/cassandra
    ports:
    - "7000:7000"
    - "7001"
    - "7199"
    - "9042:9042"
    - "9160:9160"

然后通过执行docker exec -it <container id> nodetool rebuild手动启动 cassandra 节点。

我可以在开发中使用此功能,嗯...

@jpetazzo我们在混合平台上的团队中开发 PHP 解决方案。 我们的调试器 (xdebug) 需要连接回主机上的 IDE。 在 Windows 和 Linux 上,这是“开箱即用”的,但在 mac 上,我们的开发人员必须更改 xdebug.ini 文件以特别提及他们的本地 IP。 但是 Dockerfile 处于源代码控制之下……当开发人员在编辑此文件时发生冲突时,队列不断发生冲突和发誓。 是的,有可编写脚本的解决方法,但为什么 docker for windows 和 mac 有 docker.for.win.localhost 和 docker.for.mac.localhost? 它有部分帮助,但我们仍然需要脚本来检测我们在哪个平台上进行正确设置。 它看起来要复杂得多。 请重新考虑此功能。 Docker 可能是一个陡峭的学习曲线,但像这样的问题会让你的用户在谷歌上搜索数小时后难以置信。

检查 https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds 页面有帮助,使用docker.for.mac.localhost为我们工作:)

无论好坏, docker-compose仍然是我所知道的启动 Selenium Hub 和无头 Firefox/Chrome 网格节点以测试在本地开发机器或 CI 中运行的 Web 服务器的最简单方法(启动docker 容器中的 web 服务器太慢了,不方便开发)。 这根本不是 Docker 的用途,但 Docker 是完成这项工作的最佳工具,这是 Docker 自己的错😆 唯一的问题是以适用于任何操作系统的方式轻松找出主机 ip。

@rskuipers你能解释一下你对docker.for.mac.localhost做了什么吗? 我正在尝试从容器内部发出请求以解析到主机。 我的容器在 traefik 上运行,这意味着我可以通过 domain.docker.localhost 访问它们,但是如果我尝试从容器内部访问以该 URL 开头的 URL,则无法解析。

目前我所做的是将其添加到我的docker-compose.yml中,这会在/etc/hosts中添加一行,以便域很好地解析:

extra_hosts: - "domain.docker.localhost:172.18.0.1"

IP 是我容器中的主机 IP,我可以使用ip route | awk '/^default via /{print $3}' 。 但如果可能的话,我不想硬编码......

@jzavrl我所做的只是使用docker.for.mac.localhost让我的 HTTP 请求通过在主机上运行的代理。 除了docker-compose之外,我不使用任何其他图层。

这正是我感兴趣的。您必须具体做出什么样的改变?

@jzavrl无:P 它刚刚工作。

我不明白,那你用docker.for.mac.localhost做了什么?

@jzavrl我用它而不是IP来连接。 所以docker.for.mac。 本地主机:8888

啊啊啊,现在开始有意义了。 那会试试这个。 干杯@rskuipers。

只需在您的计算机上使用 "en0" 的 ip。

例如

ssh [email protected]

'192.168.1.100' 可能来自您路由器的 DHCP 服务。

@acuthbert ,感谢您的建议。
docker.for.win.localhost在 Docker for Windows 中为我工作。 Docker 和 Windows 仍有希望。 😣

几乎没有什么技术原因不能做到这一点并满足这个线程上 90% 的人,在极端情况和情况下它并没有真正起作用,在那种情况下开发的人可能会对一个简单的集合感到满意的“用例”解释了它可能不起作用的场景。

这主要是政治垃圾,而不是实际的技术推理。 我希望其他容器引擎之一能够启动,我可以将 kubernetes 换成使用它。 那我就不用再处理这些垃圾了。

@NdubisiOnuora ,您的应用程序是什么类型的? Web应用程序?

我有 2 个控制台应用程序(主机中的 tcp-server 和容器中的 tcp-client)。
因为他们使用 tcp,所以我需要确切的 IP( docker.for.win.localhost不合适,因为它是域)。

例如,我必须在 tcp-client 中设置哪个ip:port ,如果我在 tcp-server 中设置ip:port 127.0.0.1:9595

只是将域解析为IP地址?

@orf
我想在 C# 中使用这段代码:
IPAddress hostAddr = Dns.Resolve("docker.for.win.localhost").AddressList[0];
但在此之前,我尝试 ping 到docker.for.win.localhost ,但没有看到,错误: Ping request could not find host docker.for.win.localhost. Please check the name and try again.
我的 Dockerfile:
FROM microsoft/windowsservercore
ADD . /
ENTRYPOINT powershell ping docker.for.win.localhost

万一有人错过了,我相信 18.03 的解决方案是host.docker.internal ,尽管出于某种原因,这仅适用于 Docker for Windows!? 为什么不是其他人?

编辑:没有看到评论被 Github 折叠...🤦‍♂️

为我工作:
docker run --rm -it --add-host "docker.for.localhost:$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')" alpine:latest ping docker.for.localhost

@lukasmrtvy这适用于外壳,但是docker-compose.yml怎么样?

我创建了一个容器来以通用方式解决这个问题,适用于所有平台https://github.com/qoomon/docker-host

此页面是否有帮助?
0 / 5 - 0 等级