正如标题所示,我需要能够检索docker托管的IP地址以及从主机到容器的portmap,并在容器内部完成这些工作。


当前回答

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

其他回答

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

你可以简单地使用容器名称dns访问主机系统,例如curl http://dockerhost:9200,所以不需要任何IP地址的麻烦。

我是这样做的。在这种情况下,它在docker镜像的/etc/hosts中添加了一个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容器的本地机器。

如果你启用了docker远程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的端口),然后使用node解析返回的JSON为DESIRED_PORT。

对于大多数希望自动执行此操作的应用程序来说,标准的最佳实践是:你不需要这样做。相反,你让运行容器的人注入一个外部主机名/ip地址作为配置,例如作为一个环境变量或配置文件。允许用户注入这个可以提供最可移植的设计。

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


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

如果容器在主机网络下运行,则可以直接查看主机上的路由表,以查看默认路由输出。从这个问题来看,以下几点对我有用。

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条目:

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

我有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]