docker run -p 5432:5432 postgres and back comes:
Error response from daemon: driver failed programming external connectivity on endpoint <name>:
Bind for 0.0.0.0:5432 failed: port is already allocated
Or:
Error starting userland proxy: listen tcp4 0.0.0.0:5432: bind: address already in use
Same root cause: something else is bound to port 5432 on the host. That something is either another Docker container or a process on the host. The fix is to find it, then either kill it, change its port, or pick a different host port for the new container.
Find the offender
Is it another container?
docker ps --filter publish=5432That lists containers that have published port 5432. Usually one result. If found, that's your culprit:
docker stop CONTAINER_ID
# or change its port and restartIs it a host process? On Linux/Mac:
sudo lsof -i :5432
# or
sudo ss -ltnp 'sport = :5432'lsof shows: command name, PID, user, file descriptor, type, protocol, and the address. ss is the modern Linux replacement for netstat and shows similar info.
Once you have the PID, decide whether to stop the process:
ps -p PID -o cmd=
# Confirm what it is before killing
sudo kill PIDOn Windows (PowerShell):
Get-NetTCPConnection -LocalPort 5432 -State Listen | Select-Object OwningProcess
Get-Process -Id <PID>Quick fix: pick a different host port
If you can't or don't want to free the original port, change the host port. The container port stays the same:
docker run -d -p 5433:5432 postgres:17Container port 5432 is unchanged; host-side, you reach Postgres on 5433. Connection string: postgres://...@127.0.0.1:5433/....
The -p HOST:CONTAINER order matters and trips people up. The container's port is on the right (which the container never changes). The host's port is on the left (which you choose). Mixing them up causes the container to bind on the wrong port and you to connect to the wrong one.
Bind to a specific interface
docker run -d -p 127.0.0.1:5432:5432 postgres:17Binds host port 5432 on loopback only — not on any other interface. Useful when port 5432 is "free" on loopback but already used on some external interface (rare, but happens on hosts with multiple network interfaces).
When two Docker installs fight
Sometimes there are two Docker daemons (rootful + rootless, or Docker Desktop + a separately-installed Docker Engine) and both try to claim the same port. docker ps only shows containers from the daemon your CLI is currently talking to. To check the other:
# Rootless docker as your user
DOCKER_HOST="unix:///run/user/$(id -u)/docker.sock" docker ps --filter publish=5432
# Rootful docker
DOCKER_HOST="unix:///var/run/docker.sock" docker ps --filter publish=5432If a container from the "other" Docker is the offender, stop it via that daemon.
Inside Docker Desktop's VM
On Mac and Windows, the port from your perspective is on the host, but Docker Desktop runs Linux in a VM and the actual port binding happens inside the VM. The error is the same; the diagnosis on the host (lsof, etc.) still works because Docker Desktop forwards the host port through to the VM.
Occasionally a Docker Desktop port binding gets stuck even after the container is gone. Fix:
- Restart Docker Desktop.
- If that fails, restart the host.
Stale binds are rare but happen.
Common scenarios
You started Postgres in Docker but already have Postgres on your host.
The host's Postgres binds 5432. The Docker container can't. Either:
- Stop the host's Postgres (
brew services stop postgresql,sudo systemctl stop postgresql, etc.). - Or run Docker's Postgres on a different host port:
-p 5433:5432.
You restarted a Compose stack and got the error.
A previous container is still running or wasn't cleanly removed:
docker compose down # cleans up
docker compose up -d # fresh startIf down doesn't remove the container (rare), docker rm -f $(docker ps -aq --filter name=projectname) does.
You ran docker run twice with the same -p.
The first container has the port. Stop it (docker stop CONTAINER_ID) before starting another on the same port, or use different host ports.
Port 80 / 443 conflict on macOS / Windows.
Local web servers (like a system Apache or IIS or a previously-installed nginx) often bind 80 already. Docker Desktop can't grab it. Stop the system service, or use a different host port like -p 8080:80.
Common pitfalls
- Mixing up host:container order. It's
-p HOST:CONTAINER. Container port is fixed by the image; host port is your choice. - Not realizing another container has the port. Run
docker psfirst. - Killing the offending process without identifying it. Use
ps -p PID -o cmd=first to see what it is. It might be a daemon you want to keep, and a different host port is the right answer. - Port released but
docker runstill fails. Sometimes Linux's TIME_WAIT state holds a port for up to 60 seconds after it's released. Wait a minute and retry. - Docker Desktop stale bind. Restart Docker Desktop if a container died but the port still won't free.
What to do next
- Docker Networking Basics —
-psemantics in context. - Docker Container Lifecycle — managing existing containers (stop, rm).
- docker run Cheat Sheet — full
-preference with patterns.
FAQ
Sources
Authoritative references this article was fact-checked against.
- docker run --publish — official referencedocs.docker.com



