问题描述
我正在 Docker 容器中部署应用程序。应用程序使用回调 URL 向另一台服务器发送请求。回调 URL 包含应用实际运行的主机和端口名称。
在“稳定、非动态”的测试环境中配置这个回调 URL 很容易,因为我们知道应用运行的 IP 和端口。但是在 Docker 中,回调 URL 是宿主机的 IP 地址 + docker-compose.yml 文件中配置的端口。所以这两个参数都是动态的,不能硬编码在Docker镜像中。
我需要容器中的容器信息以某种方式提供 docker 主机 IP 和暴露的端口。
这是我的容器获取docker主机IP的方式:
version: '3'
services:
my-server:
image: ...
container_name: my-server
hostname: my-server
ports:
- "1234:9876"
environment:
- DOCKER_HOST_IP=${HOST_IP}
我在启动容器时设置了主机 IP:
HOST_IP=$(hostname -i) docker-compose up
也许这不是一种优雅的方式,但这是迄今为止我能做到的最好的方式。
但我不知道如何获取容器内暴露的端口信息。
我的想法是,一旦我知道容器中的主机 IP,我就可以使用 nmap $HOST_IP
以某种方式获取打开的端口列表和 grep 以获取正确的行。但这不起作用,因为我在这台主机上运行了许多 Docker 容器,而且我无法使用 grep 选择正确的行。
这是nmap的结果:
PORT STATE SERVICE
22/tcp open ssh
111/tcp open rpcbind
443/tcp open https
5001/tcp open commplex-link
5002/tcp open rfe
7201/tcp open dlip
1234/tcp open vcom-tunnel
1235/tcp open vcom-tunnel
1236/tcp open teradataordbms
60443/tcp open unkNown
因此,当我从容器中执行 nmap
时,我可以看到主机中所有打开的端口。但是我不知道如何选择属于我所在容器的行。
我可以在 docker 启动容器之前以某种方式自定义服务名称吗?
解决方法
您应该将完整的外部可见回调 URL 传递给应用程序。
ports:
- "1234:9876"
environment:
- CALLBACK_URL=http://physical-host.example.com:1234/path
您可以想象各种有趣的场景,其中主机 IP 地址也不能直接路由。作为一个基本示例,假设您正在家里的笔记本电脑上运行容器。笔记本电脑的 IP 地址可能是 192.168.1.2/24,但这仍然是一个“私有”地址;您需要路由器的外部可见 IP 地址,而要发现这一点并不容易。
xx.xx.xx.xx /--------\ 192.168.1.1 192.168.1.2 /----------------\
------------| Router |---------------------------| Laptop |
\--------/ | Docker |
| 172.17.1.2 |
Callback address must be | Server |
http://xx.xx.xx.xx/path \----------------/
在云环境中,您可以想象一个使用负载均衡器的类似设置。您的容器可能在某个云托管实例上运行。容器可能会侦听端口 11111,然后您将其重新映射到实例上的端口 22222。但是在此之前,您有一个负载均衡器,它侦听普通 HTTPS 端口 443,执行 TLS 终止,然后转发到实例,并且您有一个连接到该负载均衡器的 DNS 名称;回调地址将是 https://service.example.com/path
,但如果没有明确告诉容器这一点,它就无法弄清楚这一点。