LearnDevOpsHands-On Labs
Troubleshooting Matrix/docker: port is already allocated
DockerHigh Severity

docker: port is already allocated

Fix "port is already allocated": run docker ps and lsof -i :PORT to find the owner, then stop it or change the host port. Covers Compose and localhost binds.

Observed Error Signature / Log Pattern
docker: Error response from daemon: driver failed programming external

Incident Overview

Fix "port is already allocated": run docker ps and lsof -i :PORT to find the owner, then stop it or change the host port. Covers Compose and localhost binds.

easy fix·6 min read·3 causes

By Vishvesh Patel·DevOps Engineer·Updated 16 September 2026

BASHDiagnostic / remediation command
docker: Error response from daemon: driver failed programming external
connectivity on endpoint api (a3f2c1d4): Bind for 0.0.0.0:3000 failed:
port is already allocated.

Error response from daemon: Ports are not available: exposing port
TCP 0.0.0.0:5432 -> 0.0.0.0:0: listen tcp4 0.0.0.0:5432: bind: address already in use

Do this first3 steps

Run these in order. Each one tells you what its output means before you change anything.

• Find out whether a container holds the port

Anything listed here owns the binding, running or exited. docker stop releases it; an exited container needs docker rm before the port comes back.

• If Docker shows nothing, it is a host process

Usually a local Postgres, another dev server or a system service. Stop that process, or publish on a different host port with -p 3001:3000.

• If you use Compose, check for another stack still up

Another project left its stack running. Change to that directory and run docker compose down. Stopping a single container leaves the rest of the stack and its network behind.

BASHDiagnostic / remediation command
docker ps -a --filter "publish=3000" --format '{{.Names}}\t{{.Status}}'

Then: the 3 causes in full

If the steps above did not settle it, these are the causes in the order they are usually responsible. Each section explains why it happens and how to confirm it.

The host port you asked Docker to publish is already bound by something. Docker cannot share a port, so the container refuses to start.

The owner is one of three things: another container, a stopped container Docker still has a reservation for, or an ordinary process on the host. Identifying which takes one command each.

Find the owner

Start with containers, since that is the usual answer:

If nothing there holds it, check the host:

A node, python or java process is a development server someone started outside Docker. docker-proxy means Docker itself still holds it. See below.

BASHDiagnostic / remediation command
docker ps -a --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' | grep 3000

Cause 1: Another container

Compose users: a project left running from another directory is the classic case, because Compose namespaces containers by project but not host ports.

BASHDiagnostic / remediation command
docker ps --filter "publish=3000" --format '{{.Names}}'
docker stop api-old

Cause 2: A stopped container still holding the reservation

The confusing one. A container that exited can leave Docker's port mapping in place, so lsof shows docker-proxy with no running container to explain it:

docker stop is not enough here. The container must be removed. If removing it does not release the port, the daemon's networking state is stale:

On Docker Desktop, restart the application. That is a blunt instrument and it does resolve the case where nothing visible owns the port.

BASHDiagnostic / remediation command
sudo lsof -i :3000

Cause 3: A host process

A locally installed PostgreSQL, MySQL, Redis or nginx conflicting with the containerised one. This is extremely common on developer machines, where 5432, 3306, 6379 and 80 are frequently taken by services installed years earlier.

Two options. Stop the host service:

Or, better, change the host port instead, so the two coexist:

Only the left-hand number changes. The container still listens on 5432 internally, so nothing inside it or in your Compose network needs adjusting.

BASHDiagnostic / remediation command
sudo lsof -i :5432

Fixing it properly in Compose

Hardcoded host ports are what make this recur. Make them configurable:

Better still, do not publish ports you do not need from the host at all. Containers on the same Compose network reach each other by service name on the container port, so a database only needs publishing if you connect to it from your own machine:

That removes the conflict entirely and is closer to how the stack runs in production.

For throwaway containers, let Docker choose:

BASHDiagnostic / remediation command
services:
  api:
    build: .
    ports:
      - "${API_PORT:-3000}:3000"
  db:
    image: postgres:17
    ports:
      - "${DB_PORT:-15432}:5432"

Bind to localhost, not everything

Worth changing while you are here:

-p 3000:3000 binds 0.0.0.0, exposing the container to your whole network, and on Linux, Docker writes iptables rules that bypass ufw and firewalld, so a port you believed was firewalled is reachable from the LAN. Prefixing 127.0.0.1: limits it to your own machine.

BASHDiagnostic / remediation command
docker run -d -p 127.0.0.1:3000:3000 myapp

A checklist

Frequently Asked Questions

How do I find what is using a port that Docker says is already allocated?

Two commands cover it. docker ps -a --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' shows every container including stopped ones and what each publishes. If none of them holds the port, sudo lsof -i :3000 or sudo ss -tlnp | grep :3000 names the host process. A result of docker-proxy means Docker itself still has a reservation, usually from a stopped container that has not been removed.

Why is a port still in use after I stopped the container?

Because stopping a container does not always release Docker's port reservation; removing it does. Run docker rm <name> rather than only docker stop. If the port is still held with no container to explain it, lsof showing docker-proxy, the daemon's networking state is stale and restarting Docker clears it. On Docker Desktop that means restarting the application.

How do I run a container when the host port is taken by a local service?

Change the host side of the mapping rather than stopping the service: docker run -p 15432:5432 postgres:17 publishes to 15432 while the container still listens on 5432 internally. Nothing inside the container or elsewhere on its Docker network needs to change, and you connect with psql -h localhost -p 15432. This is usually better than shutting down a locally installed database you may want later.

Why does Compose keep hitting port conflicts?

Because host ports are global while Compose projects are namespaced. Two projects can both try to publish 3000, and a stack left running from another directory holds it. docker compose ls lists every running project with its config file path, which finds the culprit immediately. Parameterise the host port as "${API_PORT:-3000}:3000" so it can be overridden, and stop publishing services that only other containers need.

Do I need to publish a database port in Compose?

Only if you connect to it from your own machine. Containers on the same Compose network reach each other by service name on the container port, so an API talks to db:5432 whether or not 5432 is published to the host. Removing the ports entry for internal services eliminates this class of conflict entirely and matches how the stack runs in production, where nothing exposes a database publicly.

Is -p 3000:3000 safe on a shared network?

Not especially. That form binds 0.0.0.0, making the container reachable from anything that can route to your machine, and on Linux, Docker inserts iptables rules ahead of ufw and firewalld, so a port you believe is firewalled is in fact open on the LAN. Use -p 127.0.0.1:3000:3000 to bind only the loopback interface, which is what you almost always want for local development.

Reference and practice

Learn the underlying concept

Other Docker errors

Free, comprehensive DevOps tutorials and learning roadmaps. Master Docker, Kubernetes, CI/CD, and more.

Get notified about new tutorials and features.

• Roadmaps

• Interview Prep

• Certifications

• Company

© 2026 DevOpsLesson. All rights reserved.

Need to practice this scenario?

Simulate this error condition and practice recovery commands safely in our in-browser terminal.

Open Docker Sandbox