10

I am creating a instance of my image like

docker run -P webmodule-xy

The Dockerfile for the webmodule exposes a port (e.g. 8080).

My goal now is to obtain the mapped / assigned port number which is accessible from the outside via Java. Is there a environment variable or something like that?

Usecase: The webmodule-xy should register itself on another web-application and provide its IP + Port so the other application can contact the webmodule-xy later on. IP is no problem, but the port is.

I already found this open issue on GitHub, but I can't believe that there is no simple solution. Like stated there, REST is not an option:

Allowing a container to have access to the REST API is problematic. For one thing, the REST API is read/write, and if all you need is to read your portmappings, that's a dangerous level of permissions to grant a container just to find out a few ports.

M156
  • 1,044
  • 1
  • 12
  • 29
  • I'm not directly answering your question, but perhaps you can use docker linking instead (https://docs.docker.com/userguide/dockerlinks/). It allows several docker containers to know about each other in a portable way. You may need to redesign the registration part of your application, if it is at all feasible. – ivant Nov 02 '15 at 16:25
  • 1
    Thanks for your suggestion! I know about links already and use them for e.g. database. Unfortunately I can't use them in my use case, because the two systems (module and base application) should be strictly separable. So they shouldn't be assumed to be running on the same Docker Host. – M156 Nov 02 '15 at 16:57
  • Yes, that's correct. One hack which I just thought of: you can run a second container, linked to `webmodule-xy` and use it just to register the application. It can exit after that. – ivant Nov 02 '15 at 17:04
  • Actually the hack won't work as the new image will see the internal interface, not the external. – ivant Nov 02 '15 at 18:36

1 Answers1

7

Once the container is running, you should be able to use docker inspect in order to get the port number mapped on the host by the -P option.

One can loop over arrays and maps in the results to produce simple text output:

docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' $INSTANCE_ID

Find a Specific Port Mapping

docker inspect --format='{{(index (index .NetworkSettings.Ports "8080/tcp") 0).HostPort}}' $INSTANCE_ID

I now want to get to know this random port inside the java app which runs in the container.

As detailed in "Docker, how to get container information from within the container?", you can:

  • find out a shortedned docker id by examining $HOSTNAME env var.
  • use the Docker Remote API

    GET /containers/<docker_id>/json HTTP/1.1
    

Since using Docker Remote API from a container is problematic (because of writable access), you could consider adding the port as a variable environment.

  • a docker exec would, after the docker run, add the port read from docker inspect as an environment variable and run the java app (issue 8838 ):

    docker exec -i CONTAINER_ID /bin/bash -c "export PORT=<port> && run_java-app"
    
  • The java app (from within the container) would read the environment variable

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Thanks for your answer! I am aware that this is possible by using the docker cli, but I wan to access this functionality inside a Java application. Do you suggest, that I should run this inspect command inside my java application? – M156 Nov 02 '15 at 14:12
  • @M156 Is your java app running in the container, or on the host? – VonC Nov 02 '15 at 14:12
  • It runs in the container and exposes a port, which then is randomly bound by docker via the -P argument. I now want to get to know this random port inside the java app which runs in the container. I want to tell this port to another application so it can contact my app later on over the port (from outside). – M156 Nov 02 '15 at 14:13
  • @M156 I have edited the answer to address you particular case – VonC Nov 02 '15 at 14:19
  • I know that this way could work, but "Allowing a container to have access to the REST API is problematic. For one thing, the REST API is read/write, and if all you need is to read your portmappings, that's a dangerous level of permissions to grant a container just to find out a few ports." (Source: https://github.com/docker/docker/issues/3778) – M156 Nov 02 '15 at 14:20
  • 1
    @M156 I have edited the answer to propose an alternative to using the remote API. – VonC Nov 02 '15 at 14:39
  • Ok the last proposal seems to be the only solution for now. Still a bit ugly (not your fault) and i'm looking forward for a "built in docker solution". So for the moment i'll accept your answer. – M156 Nov 02 '15 at 17:03
  • @M156 I agree it is ugly. I will follow https://github.com/docker/docker/issues/3778 with interest. – VonC Nov 02 '15 at 17:36
  • @M156 also, https://github.com/docker/docker/issues/8427#issuecomment-104560193 is encouraging. – VonC Nov 02 '15 at 17:50