Docker "port is already allocated" and "ports are not available": find who has the port
Fix Docker "Bind for 0.0.0.0:8080 failed: port is already allocated" and "Ports are not available": find the container or process using it, and Windows reserved ports.
by OhSudo ··
Checked on real software: Docker · November 2026How we check
Not sure this is your cause?Find it step by step: Container won't start →
Part of a learning path:Docker: from first container to production
docker: Error response from daemon: driver failed programming external connectivity on endpoint web (a1b2c3...): Bind for 0.0.0.0:8080 failed: port is already allocated.And a close relative, with a different cause, common on Windows and Docker Desktop:
Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:8080 -> 127.0.0.1:0: listen tcp 0.0.0.0:8080: bind: An attempt was made to access a socket in a way forbidden by its access permissions.Only one program can listen on one port at a time. Your -p 8080:80 asks for port 8080 on the host, and something already has it. The number on the right, inside the container, plays no part.
- docker run -p 8080:80wants host port 8080asks for
- Host port 8080one listener at a timerefused(fails)
- Already takenanother container, or a program on the host(breaks here)
TL;DR
docker ps --filter publish=8080 # another container?sudo ss -tlnp | grep ':8080 ' # another process? (Linux)On Windows:
Get-NetTCPConnection -LocalPort 8080 -State Listennetsh interface ipv4 show excludedportrange protocol=tcpStop what’s there, or publish on another port: -p 8081:80.
1. Another container
By far the most common, often a forgotten old run:
CONTAINER ID IMAGE COMMAND PORTS NAMESf3a91c2d7b10 nginx:1.27 "/docker-entrypoint.…" 0.0.0.0:8080->80/tcp old-webStop it. A container that’s only stopped doesn’t hold its port:
2. Docker Compose
Another project might be using the port, since each folder is its own project by default:
docker compose lsdocker ps --format 'table {{.Names}}\t{{.Ports}}\t{{.Label "com.docker.compose.project"}}'Bring it down from its folder, or by name:
docker compose -p other-project downThe terminal has this situation ready: find the project that holds 8080, bring it down by name, then start yours.
Two services in one file can’t publish the same host port, either. To run several copies of a project, make the port a variable:
services: web: ports: - "${WEB_PORT:-8080}:80"docker compose up --scale web=2 fails the same way with a fixed port, as both copies ask for it.
Use the Docker Compose Generator to get the file. It only publishes what you ask for.
3. Another program
sudo ss -tlnp | grep ':8080 'sudo lsof -i :8080 -sTCP:LISTENIf the last column of ss says docker-proxy, that’s a container, so go back to section 1. Anything else is a program on the host, such as a local web server or a development server you left running. To find what it is, and stop it for good, see address already in use. The Port Lookup tells you what normally runs on a port.
On a Mac:
sudo lsof -nP -iTCP:8080 -sTCP:LISTENmacOS itself holds port 5000 and 7000, for AirPlay Receiver. Turn it off in System Settings → General → AirDrop & Handoff, or use another port.
4. Nothing’s using it
docker ps and ss show nothing, and the error stays. The daemon may be holding on to it after a crash, or from a container that exited badly. Restart Docker:
sudo systemctl restart dockerOn Docker Desktop, use Restart from its menu. Note that restarting stops containers too, except those set up to come back.
5. Windows: excluded port ranges
The “forbidden by its access permissions” message usually means Windows has reserved that port for itself, and no program is using it at all. So your Get-NetTCPConnection shows nothing. See the reserved ranges:
netsh interface ipv4 show excludedportrange protocol=tcpStart Port End Port---------- -------- 7913 8012 8013 8112Hyper-V and WSL reserve ranges like these at boot, and they can change on each restart. So 8080 may work today, and not tomorrow. You’ve got a few options:
Choose a port that’s outside the ranges. That’s the simple answer.
Reset them, in an administrator PowerShell. This frees them until the next reservation:
net stop winnatnet start winnatReserve your port permanently, so that Windows leaves it alone. While winnat is stopped:
net stop winnatnetsh int ipv4 add excludedportrange protocol=tcp startport=8080 numberofports=1 store=persistentnet start winnatOr move Windows’s dynamic range away from common ports:
netsh int ipv4 set dynamic tcp start=49152 num=163846. Other Ports-are-not-available messages
| The end of the message | Means |
|---|---|
bind: address already in use |
Another program holds it: section 3 |
Only one usage of each socket address… |
The same thing, on Windows: Get-NetTCPConnection |
forbidden by its access permissions |
A reserved range: section 5 |
permission denied |
On Linux, a port below 1024 under rootless Docker |
For rootless Docker, use a port above 1024, or allow it with sudo sysctl net.ipv4.ip_unprivileged_port_start=80.
7. Publish on a specific address
A port is held per address. You can run two things on one port, if each one uses its own address:
docker run -p 127.0.0.1:8080:80 nginxdocker run -p 10.0.0.5:8080:80 nginxAnd 127.0.0.1 is a good idea anyway, for anything that shouldn’t be public.
Warning
A published port goes around many host firewalls like UFW, as Docker adds its own rules. So -p 5432:5432 on a server with a public address exposes that database to the internet. For local tools and databases, use 127.0.0.1:5432:5432, or don’t publish at all and let containers connect by name.
Shell, we have a problem!
Similar, but different: the same idea for a container’s name is container name is already in use. A port that’s published, and can’t be reached, is another problem: see connecting to localhost from a container. address already in use from a program on the host: see that article. And Cannot connect to the Docker daemon means Docker isn’t running at all: see that article. For the commands around this, see the Docker CLI Cheat Sheet. could not find an available, non-overlapping IPv4 address pool is Docker running out of subnets for networks.
$ ./practice.sh
Practice this in the terminal
Open the Terminal Playground with this article’s scenario loaded. It is safe and runs in your browser.
Found this useful? Share it.
Found a mistake? Let us know at contact@ohsudo.com.