Docker compose port mapping subtlety

docker-compose port mapping description

docker-compose allows you to specify port mapping between the container you're defining and the host. Thus you can reach any service you would register to this port container (i.e Apache/Nginx on 80/443, FTP on 20/21/22...) by host ports. According to compose file syntax, you can use several markups to do so :

ports:
- "3000"
- "3000-3005"
- "8000:8000"
- "9090-9091:8080-8081"
- "49100:22"
- "127.0.0.1:8001:8001"
- "127.0.0.1:5000-5010:5000-5010"
- "127.0.0.1::5000"
- "6060:6060/udp"
- "12400-12500:1240"

Problem that can arise

I took wrong habits on my early days with docker-compose, such as not double quoting port mapping specification. So above example become :

ports:
- 3000
- 3000-3005
- 8000:8000
- 9090-9091:8080-8081
- 49100:22
- 127.0.0.1:8001:8001
- 127.0.0.1:5000-5010:5000-5010
- 127.0.0.1::5000
- 6060:6060/udp
- 12400-12500:1240

Unquoted, expression like 21:21 will be handled by YAML engine by a sexagesimal notation (base-60 value expression) The integer obtained can be quite large and will definitely not be the one you expected.

  • Best case : it raises an exception on your up process because your port number computed is above the equation limit.
  • Worst case: it generates a valid free port number and you realize at runtime there is a port communcation problem.

Note this will only happens if the port is lower than 60 (to be able to enter in a modulo calculus regarding to base-60).

docker-compose documentation added a note to underline this case :

When mapping ports in the HOST:CONTAINER format, you may experience erroneous results when using a container port lower than 60, because YAML parses numbers in the format xx:yy as a base-60 value. For this reason, we recommend always explicitly specifying your port mappings as strings.

So ALWAYS quote you ports mapping in order to express them as strings.

Tags: docker, compose, port