大多数希望自动执行此操作的应用的标准最佳做法是:您不需要。相反,您让运行容器的人注入外部主机名/IP 地址作为配置,例如作为环境变量或配置文件。允许用户注入它可以为您提供最便携的设计。
为什么会这么难?因为容器将在设计上将应用程序与主机环境隔离开来。默认情况下,网络仅被命名为该容器,并且主机的详细信息受到保护,不受容器内运行的进程的影响,这些进程可能不完全受信任。
根据您的具体情况有不同的选择:
如果您的容器在主机网络中运行,那么您可以直接查看主机上的路由表以查看默认路由。来自this question,以下对我有用,例如:
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 条目注入嵌入式 VM:
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