首页 > 解决方案 > 来自容器的 docker 主机和端口信息

问题描述

我正在 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 选择正确的行。

这是 th 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 启动容器之前以某种方式自定义服务名称吗?

获取容器在主机上打开的端口号的最佳方法是什么?

标签: dockerdocker-composenmapport-scanning

解决方案


您应该将完整的外部可见回调 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,但是如果没有明确地告诉容器这个,它就无法解决这个问题。


推荐阅读