How do I avoid 'port collision' when using docker?
Stop binding to local ports and let docker-compose
pick an ephemeral port for you. In your case, your application can get to the default ports without any help. If you are following the 12 Factor App approach, then use environment variables like in the following snippet.
version: "3.3"
services:
app:
restart: always
build: .
volumes:
- ./:/app
ports:
- 3000 # will be bound to an ephemeral port
environment:
MONGODB_URL: mongodb://mongo/db # can reach port 27017 without help
mongo:
image: mongo
ports:
- 27017
This is the primary reason to make your applications configurable via environment variables or command-line flags.
You can use docker-compose port to get the ephemeral port if you need to access a docker application from the host. I routinely use a shell function like the following:
get_exposed_port() { # SERVICE PORT
docker-compose port $1 $2 | cut -d: -f2
}
Another option available as of version 3 of docker compose files is to specify a different port exposed on the host via environment variables.
So one way to do it might be like this:
version: "3.3"
services:
mysql:
container_name: mysql
image: mysql
ports:
- "${MYSQL_PORT_NUMBER:-3306}:3306"
Then, if the environment variable is defined, that value will be used. Otherwise, the default 3306
will be used.
A second feature of version 3 docker compose files that they will read environment variables from a .env
file if one exists. The .env
file must be in the directory where you run docker-compose
from.
Finally, to debug all of this, one can use docker-compose config
to emit the variable expanded docker compose file. Doing so with a .env
that looks like this:
MYSQL_PORT_NUMBER=3307
gives this result:
$ docker-compose -f mysql-port-conflict.yaml config
services:
mysql:
container_name: mysql
image: mysql
ports:
- published: 3307
target: 3306
version: '3.3'
which shows that MySQL will be made available on port 3307
of the host. Of course, any apps that want to connect to MySQL will also need to know about ${MYSQL_PORT_NUMBER}
.
HTH