Skip to content

How to Fix Docker Error: Bind Address Already in Use

Fix Docker's 'bind: address already in use' error: find the listener with ss or lsof, free the port or change the mapping, and bind to 127.0.0.1.

SDSysadmin Desk August 5, 2026 8 min read
Diagram-style cover showing a Docker container failing to bind a host port the kernel reports as already in use

You start a container and Docker stops cold with this:

Error response from daemon: driver failed programming external connectivity on endpoint web:
failed to bind host port for 0.0.0.0:8080:172.17.0.2:80/tcp: address already in use

The wording comes straight from the kernel. When Docker publishes a port it asks the operating system to bind() that host port, and the kernel refuses because another socket already owns the same address and port. The container never gets to run.

This is the same root cause as the “port is already allocated” error, just reported from a different layer. The fix follows the same path: find what’s holding the port, then decide whether to free it or move your container to a port that’s free. The commands below are for Linux hosts. On Docker Desktop the logic is identical, you just use the host OS tools to inspect ports.

Where the error comes from

A published port like -p 8080:80 has two halves. The left number, 8080, is the host port. The right number, 80, is the port inside the container. Docker binds 8080 on the host and forwards traffic into the container’s port 80.

The kernel allows exactly one listener per address and port. If anything already listens on 0.0.0.0:8080, the bind() call returns EADDRINUSE, and that surfaces as address already in use. So the real question is never “what’s wrong with Docker.” It’s “what already owns this port.”

Step 1: Rule out another container

Containers are the most common offender, so check them first. List what’s running and read the PORTS column:

docker ps

Anything publishing your host port shows up like 0.0.0.0:8080->80/tcp. Filter straight to it:

docker ps --filter "publish=8080"

A stopped container that was never removed can still hold its mapping in Docker’s records, which is enough to block a fresh bind. Show stopped containers too:

docker ps -a

Found one you don’t need? Stop and remove it:

docker stop <container-name-or-id>
docker rm <container-name-or-id>

For a Compose project you’re finished with, take it down from its folder:

docker compose down

Step 2: Find the host process holding the port

If docker ps is empty, the port belongs to a process on the host. Two tools will name it, and either is fine.

ss is part of iproute2 and ships on modern Linux. It’s the fastest way to ask “who is listening on this port”:

sudo ss -ltnp 'sport = :8080'

Read the flags as listening (-l), TCP (-t), numeric (-n), with process info (-p), filtered to source port 8080. The output names the program and PID, for example users:(("nginx",pid=812,fd=6)).

lsof shows the same thing in a different layout:

sudo lsof -i :8080

On an older host without ss, fall back to netstat:

sudo netstat -ltnp | grep ':8080'

Tools for finding what owns a port

docker ps First check — is a container publishing this host port?
sudo ss -ltnp Fast and modern. Lists listening sockets with process and PID.
sudo lsof -i :PORT Per-port view showing process, PID, and user.
sudo netstat -ltnp Legacy fallback when ss isn't available.

Step 3: Free the port or change the mapping

Now you know what’s on the port, pick the fix that fits instead of killing things on reflex.

If it’s a leftover container or a process you don’t need, stop it. For a managed service, use the service manager rather than kill:

# Example: a host Nginx sitting on 80/8080
sudo systemctl stop nginx

# Keep it from starting at boot again
sudo systemctl disable nginx

If it’s a real service you rely on, leave it running and move your container to a free host port. This is usually the safer choice. Only the host side of the mapping changes:

# Was -p 8080:80, publish on 8081 instead
docker run -d --name web -p 8081:80 nginx

In Compose, edit the ports: line and bring the stack back up:

services:
  web:
    image: nginx
    ports:
      - "8081:80"   # host 8081 -> container 80
docker compose up -d

The container still listens on 80 inside; you’ve only picked a different door on the host.

Bind to 127.0.0.1 to dodge conflicts and exposure

By default -p 8080:80 binds to 0.0.0.0, meaning every interface on the host. That invites collisions with other listeners and, worse, exposes the container to your whole network. For anything that only needs to be reached from the host itself — a database, an admin UI, a backend an app talks to locally — bind it to localhost:

docker run -d --name db -p 127.0.0.1:5432:5432 postgres:16

Or in Compose:

services:
  db:
    image: postgres:16
    ports:
      - "127.0.0.1:5432:5432"

This narrows the bind to the loopback interface, so it can’t clash with whatever’s bound on the public interface, and the service stays off the LAN. A Postgres or Redis container that nothing external should reach has no reason to sit on 0.0.0.0.

Why the port can stay busy right after you stop something

A common follow-up: “I stopped the process and the port is still taken.” Usually it’s one of these.

A TCP socket can linger in TIME_WAIT for a short window after the owning process exits. The kernel holds the address briefly to catch any straggling packets, so an immediate restart on the same port can fail with the same error. Wait a few seconds and try again, or check the state:

ss -tan | grep ':8080'

If you see the port in TIME_WAIT, it’ll clear on its own shortly. The other cause is a container that stopped but wasn’t removed — docker ps -a will show it, and docker rm clears the mapping. If a stuck container won’t go cleanly, force it:

docker rm -f <container-name-or-id>

Quick checklist

Clearing 'bind: address already in use'

  • Run docker ps and docker ps -a — is a container (running or stopped) on that host port?
  • If yes and you don't need it: docker stop + docker rm, or docker compose down
  • If no container: sudo ss -ltnp 'sport = :PORT' or sudo lsof -i :PORT to name the process
  • Real service you need? Remap your container to a free host port
  • Local-only service? Bind it to 127.0.0.1 to avoid conflicts and exposure
  • Port still busy right after stopping? Check for TIME_WAIT and wait a few seconds
  • Re-run docker run / docker compose up -d and confirm it starts

Wrapping up

bind: address already in use is the kernel telling you a host port is already taken, nothing more exotic than that. Work it in order: check docker ps and docker ps -a for a container holding the port, then ss or lsof for a host process. From there the decision is clean — stop what you don’t need, remap onto a free host port what you do, and bind local-only services to 127.0.0.1.

If you’d rather see the Docker-side version of this same conflict, read how to fix “port is already allocated”. For how published ports fit into a multi-container stack, the Docker Compose beginner guide walks through the ports: block, and the rest of the Docker & Containers guides cover more everyday fixes.

Frequently asked questions

What does 'bind: address already in use' mean in Docker?

It means the kernel refused to let Docker bind a host port because another socket is already listening on the same address and port. Docker forwards published ports through the host, so if the host port is taken, the bind fails before the container can start. Free the port or publish your container on a different host port.

Is 'bind: address already in use' the same as 'port is already allocated'?

They point at the same underlying problem — the host port is taken — but they come from different layers. 'bind: address already in use' is the kernel's error when Docker calls bind(). 'Port is already allocated' comes from Docker's own port bookkeeping, usually another container. You diagnose and fix both the same way.

How do I find which process is listening on a port in Linux?

Run sudo ss -ltnp 'sport = :8080' or sudo lsof -i :8080. Both print the listening process name and PID. Use sudo so the owning process shows up even when it belongs to another user. For a container, docker ps shows the mapping in the PORTS column.

Why does the port stay in use after I stop the container?

The socket can sit in TIME_WAIT for a short while after a process exits, so an immediate restart sometimes fails. A stopped-but-not-removed container can also still hold the mapping. Wait a few seconds, run docker ps -a to find leftover containers, and remove any you no longer need with docker rm.

How do I bind a container to localhost only?

Prefix the host side of the mapping with 127.0.0.1, for example -p 127.0.0.1:8080:80. The port is then reachable only from the host, not the wider network. This avoids clashing with anything bound on the public interface and keeps internal services off the LAN.

Can two containers share the same host port?

No. A host port maps to exactly one listener at a time. If two containers need to answer on the same external port, put a reverse proxy in front and route by hostname or path, or give each container its own host port.

Sources & further reading

Official vendor documentation referenced while writing this guide.

SD

Sysadmin Desk

Infrastructure & Cloud

Hands-on guidance for infrastructure, virtualization, and containers — Hyper-V, VMware, Docker, and the day-to-day operations work that keeps environments running.

MCSA Guru provides independent, educational IT guidance. Microsoft, Windows, Windows Server, Microsoft 365, Exchange, and Microsoft Teams are trademarks of Microsoft Corporation; Docker is a trademark of Docker, Inc. MCSA Guru is not affiliated with or endorsed by Microsoft or Docker. Always test changes in a safe environment before applying them in production.

Related guides

Fixing something right now?

Jump straight into the guide library or search for the exact error or task you are dealing with.