Docker Error Guide: 'ports are not available: exposing port' — Fix Port Binding
Fix Docker 'ports are not available: exposing port TCP': release ports held by the OS, reserved dynamic-port ranges, host firewalls, and Desktop networking so container port publishing succeeds.
- #docker
- #troubleshooting
- #errors
- #networking
Stuck on this Docker with AI error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Overview
ports are not available: exposing port means Docker asked the host operating system to bind a published port and the OS refused. Unlike port is already allocated (which Docker raises from its own bookkeeping), this error comes back from the host network stack — the port is held by another process, falls inside a reserved dynamic range, or is blocked by the platform’s networking layer (common on Docker Desktop for Windows/macOS with the WSL2 or hypervisor proxy).
The literal message names the port and the OS-level cause:
Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:50051 -> 127.0.0.1:0: listen tcp 0.0.0.0:50051: bind: An attempt was made to access a socket in a way forbidden by its access permissions.
On Linux the underlying reason is typically:
Error response from daemon: ports are not available: exposing port TCP 0.0.0.0:8080 -> 0.0.0.0:0: listen tcp 0.0.0.0:8080: bind: address already in use
Symptoms
docker run -pordocker compose upfails at container start withports are not available: exposing port.- The port is not published by any other container, yet the bind still fails (a non-Docker process or an OS reservation holds it).
- On Windows, ports in certain ranges fail intermittently after reboots (Hyper-V/WinNAT reserved ranges).
- A privileged low port (<1024) fails when the daemon or user lacks permission.
Common Root Causes
- A non-Docker process owns the port — a locally running service, IDE, or system daemon already listening on it.
- Windows dynamic-port / Hyper-V reservations —
winnatreserves ranges of ephemeral ports; a published port landing inside one is refused by the OS. - Privileged port without permission — binding a port below 1024 when running rootless or without the capability.
- Host firewall / security software blocking the bind.
- Docker Desktop networking stuck — the vpnkit/WSL2 proxy holding stale reservations after sleep/resume.
- Another container on the same host port — the classic collision, surfaced here as an OS-level bind failure.
Diagnostic Workflow
Find what is holding the port on Linux:
sudo ss -ltnp | grep ':8080'
sudo lsof -iTCP:8080 -sTCP:LISTEN
On Windows, check the reserved dynamic-port ranges that WinNAT excludes:
netsh interface ipv4 show excludedportrange protocol=tcp
netstat -ano | findstr :50051
Confirm no Docker container already publishes it:
docker ps --format '{{.Names}}\t{{.Ports}}' | grep 8080
Read the daemon’s precise reason:
journalctl -u docker --since '5 min ago' | grep -i 'ports are not available\|bind:'
Example Root Cause Analysis
A Windows developer’s gRPC container failed after a laptop reboot with:
Ports are not available: exposing port TCP 0.0.0.0:50051 ... bind: An attempt was made to access a socket in a way forbidden by its access permissions.
Nothing was listening on 50051 (netstat -ano | findstr :50051 was empty), so it was not a normal collision. netsh interface ipv4 show excludedportrange protocol=tcp revealed that Hyper-V’s WinNAT had reserved a dynamic range that swallowed 50051 after the reboot — the OS itself was forbidding the bind.
The fix was to restart the Windows NAT service (net stop winnat then net start winnat), which released the stale reservation, after which the container published cleanly. For a durable fix, the team moved the service to a fixed port outside the reserved ephemeral ranges and, where needed, added an explicit exclusion so the OS would not reclaim it.
Prevention Best Practices
- Pick stable ports outside the ephemeral range (avoid the OS dynamic-port window, typically 49152–65535) for long-lived published services.
- On Windows, reserve or exclude fixed ports so WinNAT will not reclaim them after reboots (
netsh int ipv4 add excludedportrange). - Check for host listeners before publishing in scripts (
ss -ltnp/netstat) and fail fast with a clear message. - Avoid privileged low ports unless necessary; publish high and front with a reverse proxy.
- Restart Docker Desktop / winnat after sleep-resume issues that leave stale reservations.
- Standardize a port map across the team so two services never claim the same host port.
Quick Command Reference
sudo ss -ltnp | grep ':8080' # Linux: who holds the port
sudo lsof -iTCP:8080 -sTCP:LISTEN # alternative listener lookup
docker ps --format '{{.Ports}}' # ports Docker already publishes
# Windows:
netsh interface ipv4 show excludedportrange protocol=tcp
net stop winnat && net start winnat # release stale reservations
netstat -ano | findstr :50051 # find the PID on Windows
Conclusion
ports are not available: exposing port is the host OS — not Docker’s allocator — refusing the bind. Identify the real holder: a non-Docker listener, a reserved dynamic-port range (especially on Windows), a privileged-port restriction, or firewall software. Choose stable ports outside the ephemeral range, exclude them from OS dynamic reservations, and check for listeners before publishing. For the daemon-side collision variant, see the port is already allocated guide and the full Docker guides.
Fixed it? Get 500 Docker with AI & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Stuck on this? Start guided troubleshooting
Open an interactive diagnostic session with this error already loaded. Work a step-by-step plan, record what each check returns, land on a root cause, and export a clean incident summary — no account needed to start.
Did this fix your issue?
Solved it a different way?
Share the fix that worked for you — reviewed, then published to help the next engineer.
That looks like it may contain a secret (key, token, password, or connection string). Please remove it — a note with a detected secret can’t be published.
Thanks — that helps. Published notes appear after a quick review.
Trending errors this week
The error guides other engineers are actually reading right now.
- 1mount: wrong fs type, bad option, bad superblock
- 2Docker 'failed to set up container networking': Fix the Bridge and IP Pool
- 3Docker 'failed to create shim task': How to Fix the containerd Runtime Error
- 4Transport endpoint is not connected
- 5modprobe: FATAL: Module not found
- 6mount: wrong fs type, bad option, bad superblock
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.