Skip to content

Compose !reset & Port Stripping

Running many compose projects side by side fails the moment two of them publish the same host port — bind: address already in use. MultiDocker sidesteps this by removing host port mappings from every project, not by trying to renumber them.

Docker Compose merges lists additively. If your original file has:

services:
db:
ports:
- "3306:3306"

…then an override that also sets ports: would append to that list, not replace it. The 3306:3306 mapping would survive the merge and still collide with the next project’s database.

Compose v2 introduced the !reset YAML tag precisely for this: it clears a value that an earlier file in the merge set, rather than merging into it. MultiDocker’s overrides use:

services:
db:
ports: !reset []

This wipes the host port bindings entirely. The container still listens on its internal port inside the docker network — you just can’t reach it from a host localhost:<port> mapping anymore. And you don’t need to: routing happens through Traefik on the shared edge network, and databases are reached via container DNS or mdocker inspect.

Once ports are stripped, reachability comes from two mechanisms instead:

  • HTTP(S) traffic flows through the edge stack: Traefik terminates TLS on 127.0.0.1:443 and routes by hostname to the container’s internal port (declared in the override’s loadbalancer.server.port label).
  • Databases and other TCP services are reached over the docker network — with OrbStack, every container is addressable as <service>.<project>.orb.local. See Accessing Databases from the Host.

!reset handles the ports MultiDocker controls. If a foreign process (a stray Apache, a system service) already holds port 80, 443 or 53, that’s a different problem — MultiDocker’s port-conflict pre-flight detects it before up and either remaps or refuses, rather than letting the stack fail cryptically.