正如标题所示,我需要能够检索docker托管的IP地址以及从主机到容器的portmap,并在容器内部完成这些工作。
当前回答
另一种方法是基于traceroute,它在Linux主机上为我工作,例如在一个基于Alpine的容器中:
traceroute -n 8.8.8.8 -m 4 -w 1 | awk '$1~/\d/&&$2!~/^172\./{print$2}' | head -1
它花了一点时间,但列出了第一跳的IP,该IP不是以172开头的。如果没有成功响应,则尝试使用-m 4参数增加测试跳数的限制。
其他回答
如果你启用了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
在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'/.$//'`
从版本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
唯一的方法是在创建容器时将主机信息作为环境传递
run --env <key>=<value>
推荐文章
- 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容器获取环境变量