Skip to content

Port-Conflict Pre-flight

Stripping host ports with !reset removes conflicts between MultiDocker projects. But a project might still need to publish a host port itself — and a foreign process (a stray database, a system service) may already hold it. The port-conflict pre-flight catches that before up, instead of letting docker compose fail with a cryptic bind error.

mdocker up calls check_service_port_conflicts before starting any container. For each host port a service wants to publish, it checks whether the port is already in use by a process outside the project. If everything is free, up proceeds normally.

If a conflict is found, the behaviour depends on your flags:

Flag Behaviour on conflict
(default) Suggests a free replacement port; refuses with exit code 2 if none is applied
--auto-remap-ports Automatically picks a free replacement and continues
--no-port-check Skips the pre-flight entirely

When a replacement port is chosen, it isn’t a one-off. MultiDocker persists it so the same service keeps the same host port on every subsequent start:

  1. It’s written to the registry under .projects[<name>].port_overrides:

    "port_overrides": { "redis": { "6379": 6380 } }
  2. render_ports_override renders that into ~/.config/multi-docker/overrides/<name>.ports.yml.

  3. That file is appended to the COMPOSE_FILE chain, after the main override:

    Terminal window
    COMPOSE_FILE="<original>:<name>.override.yml:<name>.ports.yml"

So the remap survives restarts, and the CLI stays deterministic — a service always lands on the port it was assigned.

Port overrides are ordinary registry data. They’re managed through lib/common.sh helpers (registry_set_port_override, registry_get_port_overrides, registry_clear_port_overrides) and re-rendered on rerender.