Skip to main content

Docker · troubleshooting

Bind for 0.0.0.0:PORT failed: port is already allocated

Something already holds the host port you asked to publish. Usually another container — sometimes a stopped one that still owns the binding, and sometimes a process on the host that has nothing to do with Docker.

Run this first

step 1 of 3
docker ps --format 'table {{.Names}}	{{.Ports}}' | grep -F ':8080'

Look for Any container publishing the same host port.

Checks the obvious case first — another running container.

Work out which cause you have

A few questions to narrow the list. Every answer ends in a command that confirms or rules the cause out — this cannot see your cluster, so nothing here is a certainty until you have checked.

Narrow it down

0 answered · nothing is sent anywhere

Does `docker ps` show another container publishing that host port?

Cause space

4 of 4 still possible

  • Another container already publishes that host portCommon
  • A process on the host holds the port, unrelated to DockerCommon
  • A stopped or created container still holds the reservationOccasional
  • A scaled compose service is trying to publish the same fixed port more than onceOccasional

Nothing ruled out yet. Answer the question above and the branches your answer eliminates will strike through here.

Check it with a tool

Or diagnose it manually

In this order. The first command usually contains the whole answer.

  1. Step 1

    docker ps --format 'table {{.Names}}	{{.Ports}}' | grep -F ':8080'

    Checks the obvious case first — another running container.

    Look for Any container publishing the same host port.

  2. Step 2

    docker ps -a --format 'table {{.Names}}	{{.Status}}	{{.Ports}}' | grep -F '8080'

    Includes stopped containers, which can still hold the reservation while being invisible to `docker ps`.

    Look for A non-running container that still lists the port.

  3. Step 3

    sudo ss -tlnp | grep ':8080' || sudo lsof -iTCP:8080 -sTCP:LISTEN

    If Docker is not holding it, something on the host is. This is the step people skip.

    Look for A PID that is not dockerd or docker-proxy.

Every cause, and how to fix it

Ordered by how often each one turns out to be the answer.

Another container already publishes that host port

Common

The most common case, and often a previous run of the same stack that was never stopped. Compose projects with different names will happily run side by side and collide on ports.

Confirm

docker ps --format 'table {{.Names}}	{{.Ports}}' | grep -F ':8080'

Any container listing `0.0.0.0:8080->` in its ports.

Fix

  • Stop the container that holds it, or publish this one on a different host port — the container port does not need to change.
  • For a duplicated compose stack, bring the old one down with `docker compose down` rather than stopping containers individually, so networks and orphans go too.
docker run -p 8081:3000 myapp   # host port changed, container port unchanged

Only the left-hand number is contended. The application inside still listens on 3000.

A process on the host holds the port, unrelated to Docker

Common

A local dev server, a database installed directly on the machine, or a system service. Docker cannot see it and will not mention it, so the error implies a container conflict that does not exist.

Confirm

sudo ss -tlnp | grep ':8080' || sudo lsof -iTCP:8080 -sTCP:LISTEN

A PID and process name that is not `dockerd` or `docker-proxy`. That is your answer, and it is not a Docker problem.

Fix

  • Stop the host process, or pick a different host port for the container.
  • On macOS and Windows this is worth checking early — the Docker VM's port forwarding makes the error identical while the conflict is on the host side.

A stopped or created container still holds the reservation

Occasional

A container that failed to start, or was created without being run, can still own the port mapping. It does not appear in `docker ps`, which is why the port looks free.

Confirm

docker ps -a --format 'table {{.Names}}	{{.Status}}	{{.Ports}}' | grep -F '8080'

A container with a non-running status that still lists the port.

Fix

  • Remove it with `docker rm`. Stopping is not always enough — the reservation goes with the container object.
  • `docker container prune` clears all stopped containers at once, which is worth checking before running.
docker rm <container>

A scaled compose service is trying to publish the same fixed port more than once

Occasional

Scaling a service that publishes a fixed host port means every replica asks for the same port. The first succeeds and the rest fail, which reads as a mysterious partial start-up.

Confirm

docker compose config | grep -A3 'ports:'

A fixed `HOST:CONTAINER` mapping on a service you are scaling above one replica.

Fix

  • Publish a port range, or let Docker assign the host side by giving only the container port.
  • For anything real, put the replicas behind a proxy rather than exposing each one on its own host port.

Understanding it properly

Skip this if you are mid-incident — the working part of the page is above. Worth reading afterwards, because understanding the mechanism is what stops the next one.

What is actually happening

Publishing a port with `-p 8080:3000` asks the Docker daemon to bind host port 8080. A host port can have exactly one owner, so if anything already holds it, the bind fails and the container never starts.

The confusing part is who counts as "anything". A running container is the obvious case. A container in a created-but-not-started state can also hold the reservation. And a plain host process — a local development server, another instance of the same stack, a system service — will hold it too, invisibly from Docker's point of view.

This is a host-level conflict rather than a container problem, which is why looking inside the container tells you nothing.

How to tell this is your problem
WhereWhat you see
docker run / docker compose up`Error response from daemon: ... Bind for 0.0.0.0:8080 failed: port is already allocated`
docker psAnother container listing the same host port in its PORTS column.
ss -tlnp / lsof -iA non-Docker process listening on the port.

How to know it is actually fixed

  • The container starts and `docker ps` shows `0.0.0.0:<host>-><container>/tcp` with the arrow present.
  • A request to the host port reaches the application rather than being refused.

Stopping it happening again

  • Prefer letting Docker assign host ports for anything you do not need at a fixed address, and look the assignment up when you need it.
  • Use `docker compose down` rather than `stop` when finishing with a stack, so container objects and their reservations are removed.
  • Keep local host services on ports that your compose files do not use — colliding with your own Postgres install is a recurring waste of an afternoon.

Did this get you to an answer?

No text box on purpose — please do not paste production logs anywhere

Sources

Behaviour described here is drawn from official documentation. Where a figure could not be confirmed on an official page it is attributed in the text rather than stated as canonical.

Related

Bind for 0.0.0.0:PORT failed: port is already allocated — causes, diagnosis and fix | DevOps Insights