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?
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