Issue with Exposing a Range of Ports in Docker Compose

Hi there! :grin:

As mentioned in the Docker documentation, I’m trying to expose a range of around 300 ports. However, the result I get is just 0/tcp.

Is this a bug, or am I doing something wrong? I’ve been racking my brain over this :face_with_head_bandage:.

I’ve tried multiple configurations, but I keep getting the same result.

Any help would be greatly appreciated!

Thanks!

Docker Compose version v2.29.1

On Debian or windows

Compose File

services:
  hello_world:
    image: debian
    expose:
     - 58787-59000
    command:
      - /bin/bash
      - -c
      - |
         while [ 1 ]; do echo " hello world !" ;sleep 30 ;done;

When i run

sudo docker compose up -d --build 

EXPECTED

debian                             "/bin/bash -c 'while…"   3 minutes ago    Up 3 minutes                    58787-5900/tcp
...
        "Config": {
            "Hostname": "3f9dea0b4aa7",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": true,
            "AttachStderr": true,
            "ExposedPorts": {
                "58787-59000": {}
…
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "*****************************",
            "SandboxKey": "/var/run/docker/netns/**************",
            "Ports": {
                "58787-59000/tcp"

RESULT

   debian                             "/bin/bash -c 'while…"   7 seconds ago    Up 6 seconds                    0/tcp
...
        "Config": {
            "Hostname": "3f9dea0b4aa7",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": true,
            "AttachStderr": true,
            "ExposedPorts": {
                "58787-59000": {}
…
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "*****************************",
            "SandboxKey": "/var/run/docker/netns/**************",
            "Ports": {
                "0/tcp": null

If you want to publish container ports to host ports, you need to use ports.

services:
  hello_world:
    image: debian
    ports:
     - "58787-59000:58787-59000"
    command:
      - /bin/bash
      - -c
      - |
         while [ 1 ]; do echo " hello world !" ;sleep 30 ;done;

See: https://docs.docker.com/reference/compose-file/services/#ports

Hi Meyay,

Thank you for the quick response.

I don’t want to map the port on the host; I just need to open it within the Docker Compose stack.

After extensive testing, I found a way to achieve this. I realized that it only works on the Dockerfile side.

:rocket: WORKS!

docker-compose.yml

services:
  hello_world:
    container_name: "hello_world"
    build:
      context: .
      args:
        - PORTS=58787-59000

Dockerfile

FROM debian:latest

ARG PORTS

COPY ./init.sh /etc/init.sh

EXPOSE $PORTS

CMD ["/etc/init.sh"]

init.sh

#!/bin/bash
while [ 1 ]; do
    echo "Hello, world!";
    sleep 30;
done;

:no_entry_sign: DOESN’T WORK IN THE DOCKER COMPOSE AT ALL

docker-compose.yml


services:
  hello_world:
    container_name: "hello_world"
    build:
      context: .
    expose:
      - "${PORTS}"
    environment:
      - PORTS=58787-59000

Dockerfile

FROM debian:latest

COPY ./init.sh /etc/init.sh

CMD ["/etc/init.sh"]

It doesn’t work on the Compose side, only on the Dockerfile side, and I’m not sure why.

I assume the ARG directive works because it passes the argument to the Dockerfile before it’s built. My understanding is that ENV simply passes variables to Docker Compose, allowing me to pass variables from a .ENV file to the ARG in the Docker Compose file, which should complete the job.

Ports are always open between containers in a stack. That EXPOSE is just simply a metadata for load balancers and other services that automatically detects where to forward requests.

As for the original question, although you don’t need the expose, the only difference I see is that the documentation uses quotation marks and you didn’t.

Dockerfile does not support port ranges.

https://docs.docker.com/reference/dockerfile/#expose

Hi Rimelek,

I hoped that using quotation marks would solve my problem, but unfortunately, it didn’t.

I understand that exposing ports inside the container is unnecessary for the container itself. However, I pass the ports to my service during its construction because I want it to advertise the port it is listening on.

I hope that’s clear.

I see. Then it is not to open ports after all. I tested your port range which didn’t work and I tested 3000-4000 which worked so I guess the chosen port range is not supported. I’m not sure why

Well, if “EXPOSE” is not intended for exposing ports, then the term seems inappropriate.
They should consider using a term like “ROUTING_PORT” or something more suitable. :neutral_face:
But who cares ? maybe cysco ingenior :stuck_out_tongue_winking_eye:

Additionally, using "PORT" works but automatically maps a random port on the host, which is not ideal.

Port range 3000-4000 directly in the Compose file doesn’t work either for me.

services:
  hello_world:
    container_name: "hello_world"
    build:
      context: .
    expose:
      - 3000-4000 

It still shows: 0/TCP.

The only workaround I’ve found is to modify the Dockerfile, which isn’t ideal if I want to use a pre-built Docker Hub image directly in the Docker Compose file. I haven’t even tested if it’s truly “opening/routing” the port correctly.

I personally don’t care much as I almost never use it when I can set the port in a label for a load balancer, but yes, we are saying it for a long time on the forum :slight_smile: just haven’t proposed a change yet. Mentioning it more clearly in the documentation could help too.

For me too… at least in the command line when listing containers, but not the container inspect output which I checked last time. So Docker knows about the metadata.

docker container inspect hello_world --format '{{ json .Config.ExposedPorts }}'

Output:

{"58787-59000/tcp":{},"80/tcp":{}}

So yur services should be able to detect the port range, the CLi just has a bug apparently. I’m not sure why I did not see it when I first tested your port range. I remembered to see 0/tcp in the container inspect output, but I was either wrong or my original compose file (before your hello world short example) worked differently. I tried to restore the original file, although not perfectly, but I still see the right port.