正如标题所示,我需要能够检索docker托管的IP地址以及从主机到容器的portmap,并在容器内部完成这些工作。
当前回答
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地址(如果没有网络访问,则没有)。从18.03开始,我们的建议是连接到特殊的DNS名称host.docker.internal,它将解析为主机使用的内部IP地址。这是为了开发目的,不能在Mac Docker Desktop以外的生产环境中工作。
其他回答
对于大多数希望自动执行此操作的应用程序来说,标准的最佳实践是:你不需要这样做。相反,你让运行容器的人注入一个外部主机名/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
更新:在Mac版Docker上,从18.03版本开始,你可以使用host. Docker .internal作为主机的IP。请看aljabear的回答。对于以前版本的Mac Docker,以下答案可能仍然有用:
在Docker for Mac上,docker0桥不存在,所以这里的其他答案可能不起作用。然而,所有流出的流量都是通过你的父主机路由的,所以只要你试图连接到一个它识别为自己的IP(而docker容器并不认为是自己),你应该能够连接。例如,如果你从父机器运行:
ipconfig getifaddr en0
这应该会显示你的Mac在当前网络上的IP地址,你的docker容器也应该能够连接到这个地址。如果这个IP地址发生了变化,这当然是一件痛苦的事情,但是你可以在你的Mac上添加一个自定义环回IP,通过在父机器上做这样的事情,容器不会认为它是自己:
sudo ifconfig lo0 alias 192.168.46.49
然后,您可以在docker容器内使用telnet测试连接。在我的例子中,我想连接到一个远程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与您自己网络上的某些内容不冲突。
从版本18.03开始,您可以使用host.docker.internal作为主机的IP。
适用于Mac的Docker, Windows的Docker,以及其他平台。
这是mac专用docker.for.mac的更新。Localhost(17.06版后可用)和docker.for.mac.host.internal(17.12版后可用),它们也可以在该平台上运行。
注意,在Mac和Windows文档中,这仅用于开发目的。
例如,我在主机上设置了环境变量:
MONGO_SERVER=host.docker.internal
在我码头式的写作中。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
在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'/.$//'`
如果您在Service Fabric集群上运行Windows容器,则主机的IP地址可以通过环境变量Fabric_NodeIPOrFQDN获得。服务Fabric环境变量
推荐文章
- Linux命令将域名转换为IP
- 试图连接到https://index.docker.io时,网络超时
- 为每个Docker图像查找图层和图层大小
- 如何避免在为Python项目构建Docker映像时重新安装包?
- 如何用docker-compose更新现有图像?
- 如何在构建docker期间设置环境变量
- 拉访问拒绝存储库不存在或可能需要docker登录
- 如何在ENTRYPOINT数组中使用Docker环境变量?
- Docker:容器不断地重新启动
- Mac/OS X上的/var/lib/docker在哪里
- 如何用docker-compose标记docker图像
- 从IP地址获取位置
- 从环境文件中读入环境变量
- 禁用特定RUN命令的缓存
- 从Docker容器获取环境变量