Resolving port overlaps when using Docker compose
2022-09-21 | devops, docker
Scenario #
- Front-end container
front
, serving a webapp on port 9001 - Back-end service container
back
, serving an API on port 80 - Primary Objective: Reach and query
back
container from thefront
, using its service name:http://back/...
- Secondary Objective: Have a way to reach both
front
andback
from the host machine for troubleshooting
Problem #
My first attempt was to use port mapping for both - the front must be available on 80 to be able to use it ’nicely’ in a browser, and the back must be on port 80 so that it can be queried ’nicely’ in code without thinking about the port. Example below:
services:
front:
image: front-end-container:latest
ports:
- 80:9001
back:
image: back-end-container:latest
ports:
- 80:80
This will fail with port is already allocated
as localhost:80
can only host one service at at time.
Solution: Connect containers with expose
#
Use Docker compose configuration option Expose:
Expose ports without publishing them to the host machine - they’ll only be accessible to linked services. Only the internal port can be specified.
Expose “drills a hole in to the container”, and nothing else. We can have a 100 containers, all with the same ports opened with this option. There is no port mapping - the service running inside within must be configured to use the same port to be visible via that “hole”.
In the example below, instead of both containers being served over port 80 on localhost
, we serve the front-end via 80 using port mapping as normal.
For the back-end we use expose
to open the important port 80 for the front-end to query, and use a normal port
mapping to serve the back-end on localhost:8080
instead to enable troubleshooting and avoiding the overlap on localhost:80
.
services:
front:
image: front-end-container:latest
ports:
- 80:9001
back:
image: back-end-container:latest
ports:
- 8080:80
expose:
- 80 # the key bit - port used by other containers to access this container
As a result, with this configuration we can happily:
- Query
back
from thefront
withhttp://back/api/v2/...
- same as inside kubernetes - Access the
front
fromhttp://localhost:80
orhttp://localhost
- Access the
back
fromhttp://localhost:8080