Search code examples
pythondockerdocker-composeuwsgi

Get exposed port from within docker-compose


I have a docker-compose.yml file as follows:

version: "3.9"
services:
  server:
    build: .
    ports:
      - "8086"
    environment:
      - PORT=8086

a dockerfile:

FROM python:3.8

RUN python -m pip install --upgrade pip
RUN pip install pipenv

COPY Pipfile* /app/

RUN cd /app &&  pipenv lock --keep-outdated --requirements > requirements.txt

RUN pip install -r /app/requirements.txt

COPY . /app/src

WORKDIR /app/src

EXPOSE ${PORT}

CMD uwsgi --http :${PORT} --wsgi-file server.py --callable main

So basically, I am running a server on a given port, which I expose in my Dockerfile and docker-compose. However, when I run two instances of these containers, I need a way for them to each use their own port. I also cannot hardcode values as I need to be able to scale to n instances. So rather than using the environment variable PORT, I need to somehow get each port from within the running container, expose it, and run the server on that port.

When I call docker-compose up --scale server=2 to run two server containers, I am unable to send HTTP requests because the port mappings do not match up.

Essentially what I am trying to do is have each container run uwsgi using the port allocated to it by docker-compose. Is there any way to achieve this in a nice manner?

Example: enter image description here

Source: https://github.com/distribworks/dkron


Solution

  • You're missing the HOST_PORT part in your server service definition. A service's port definition should be HOST_PORT:CONTAINER_PORT as per https://docs.docker.com/compose/networking/. Otherwise a random HOST_PORT will be chosen.

    You can clone a working sample environment here or see it working here.

    You can always see which port Docker Compose is choosing by issuing:

    jdsalaro$ docker ps
    
    CONTAINER ID   IMAGE                                                         COMMAND                  CREATED          STATUS          PORTS                     NAMES
    de0120c61c1e   65896179-get-exposed-port-from-within-docker-compose_server   "/bin/sh -c 'uwsgi -…"   12 seconds ago   Up 11 seconds   0.0.0.0:49157->8086/tcp   65896179-get-exposed-port-from-within-docker-compose_server_1
    

    To fix your problem, just provide a HOST_PORT as mentioned:

    version: "3.9"
    services:
      server:
        build: .
        ports:
          - "8086:8086"
        environment:
          - PORT=8086
    

    When using --scale, for example --scale server=4, one can provide a range of ports as HOST_PORT instead as follows:

    version: "3.9"
    services:
      server:
        build: .
        ports:
          - "8000-8004:8086"
        environment:
          - PORT=8086