Search code examples
dockerdocker-composenmapport-scanning

docker host and port info from the container


I am deploying an application in a Docker container. The application sends requests to another server with a callback URL. The callback URL contains the host and port name where actually the app runs.

To configure this callback URL in a "stable, non-dynamic" test environment is easy because we know the IP and port where the app runs. But in Docker, the callback URL is the IP address of the host machine + the port that was configured in the docker-compose.yml file. So both parameter is dynamic, can not be hardcoded in the Docker image.

I need the docker host IP and the exposed port by the container info somehow in the container.

This is how my container gets the docker host machine IP:

version: '3'
services:
    my-server:
        image: ...
        container_name: my-server
        hostname: my-server
        ports:
            - "1234:9876"
        environment:
            - DOCKER_HOST_IP=${HOST_IP}

I set the host IP when I spin up the container:

HOST_IP=$(hostname -i) docker-compose up

Maybe this is not an elegant way but this is the best that I could do so far.

But I have no idea, how to get the exposed port info inside the container. My idea was that once I know the host IP in the container, I can use nmap $HOST_IP to get the opened port list and grep for the proper line somehow. But this does not work, because I run many Docker containers on this host, and I am not able to select the proper line with grep.

here is the result of 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

So when I execute nmap from the container then I can see all of the opened ports in my host machine. But I have no idea, how to select the line which belongs to the container where I am.

Can I can customize somehow the service name before docker spin-up the containers?

What is the best way to get the port number that was opened on the host machine by the container?


Solution

  • You should pass the complete externally-visible callback URL to the application.

    ports:
      - "1234:9876"
    environment:
      - CALLBACK_URL=http://physical-host.example.com:1234/path
    

    You can imagine an interesting variety of scenarios where the host IP address isn't directly routable either. As a basic example, say you're running the container, on your laptop, at home. The laptop's IP address might be 192.168.1.2/24 but that's still a "private" address; you need your router's externally-visible IP address, and there's no easy way to discover that.

    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                          \----------------/
    

    In a cloud environment, you can imagine a similar setup using load balancers. Your container might run on some cloud-hosted instance. The container might listen on port 11111, and you remap that to port 22222 on the instance. But then in front of this you have a load balancer that listens on the ordinary HTTPS port 443, does TLS termination, and then forwards to the instance, and you have a DNS name connected to that load balancer; the callback address would be https://service.example.com/path, but without explicitly telling the container this, there's no way it can figure this out.