How to fix Error starting userland proxy: listen tcp6 [::]:80: bind: address already in use in Docker

DockerBEGINNERMEDIUMUpdated Dec 6, 2025ยท 242 views

The 'listen tcp6 bind: address already in use' error occurs when Docker attempts to bind a container port to an IPv6 address that's already occupied. Find and stop the conflicting process, bind to IPv4 only, or use a different port.

Quick fix

Fixes Error starting userland proxy: listen tcp6 [::]:80: bind: address already in use

# Check both IPv4 and IPv6 bindings on the port
sudo lsof -i :80

# Or use netstat to see all listeners
sudo netstat -tlnp | grep :80

# On systems with ss (modern replacement for netstat)
sudo ss -tlnp | grep :80
  1. Identify what's using the port
  2. Stop conflicting system services
  3. Check for other Docker containers using the port
  4. Force IPv4-only binding
docker โ€” error
# Check both IPv4 and IPv6 bindings on the port
sudo lsof -i :80
# Or use netstat to see all listeners
sudo netstat -tlnp | grep :80
# On systems with ss (modern replacement for netstat)
sudo ss -tlnp | grep :80
Error starting userland proxy: listen tcp6 [::]:80: bind: address already in use

What this error means

The "listen tcp6 [::]:80: bind: address already in use" error in Docker occurs when you try to start a container with port mapping, but the specified port is already occupied on the IPv6 network stack. By default, Docker binds to both IPv4 (0.0.0.0) and IPv6 (::) addresses when you use port mapping like `-p 80:80`. The `[::]:` in the error message indicates Docker is trying to bind to all IPv6 interfaces on port 80. The double colon `::` is IPv6 shorthand for "all zeros" (equivalent to 0.0.0.0 in IPv4). This error typically means another process, Docker container, or system service is already listening on that port. Common culprits include web servers like nginx or Apache, other Docker containers, or services that started automatically on boot. The tcp6 socket type can accept both IPv4 and IPv6 connections, so even an IPv6 binding can block IPv4 connections to the same port.

Typical symptoms

  • Docker container fails to start with 'listen tcp6' error mentioning the port
  • Error message shows 'Error starting userland proxy' followed by tcp6 and the port
  • Container works when using a different port number
  • Error occurs specifically on port 80, 443, or other common web ports
  • docker-compose up fails after system reboot when services auto-start
  • The same container worked before but fails after installing a web server

Common causes

  1. A web server (nginx, Apache, Caddy) is running on the host and binding to the same port
  2. Another Docker container is already using the same host port
  3. A system service started on boot before your Docker container
  4. A previous container didn't shut down cleanly and the port is still held
  5. Both IPv4 and IPv6 sockets are bound to the same port by different processes
  6. The Docker daemon or userland proxy from a previous run is still holding the port
  7. On Linux, systemd services may have grabbed the port during startup

How to fix "Error starting userland proxy: listen tcp6 [::]:80: bind: address already in use"

1Identify what's using the port

Find which process is occupying the port using lsof or netstat. Since the error mentions tcp6, check both IPv4 and IPv6 bindings:

bash
# Check both IPv4 and IPv6 bindings on the port
sudo lsof -i :80

# Or use netstat to see all listeners
sudo netstat -tlnp | grep :80

# On systems with ss (modern replacement for netstat)
sudo ss -tlnp | grep :80

Look for processes in the output - common ones include:
- nginx - nginx web server
- apache2 or httpd - Apache web server
- docker-proxy - another Docker container
- node - Node.js application

2Stop conflicting system services

If a web server or other service is using the port, stop it:

bash
# Stop nginx
sudo systemctl stop nginx
sudo systemctl disable nginx  # Prevent it from starting on boot

# Stop Apache
sudo systemctl stop apache2   # Debian/Ubuntu
sudo systemctl stop httpd     # RHEL/CentOS
sudo systemctl disable apache2

# Stop any other conflicting service
sudo systemctl stop <service-name>

If you need the service to coexist with Docker, consider changing its port configuration instead of disabling it.

3Check for other Docker containers using the port

Another Docker container might be using the port:

bash
# List running containers and their ports
docker ps --format "table {{.Names}}	{{.Ports}}"

# Find containers specifically using port 80
docker ps --filter "publish=80"

# Stop the conflicting container
docker stop <container_name>

If using docker-compose, make sure you're not running multiple compose files that use the same port.

4Force IPv4-only binding

If you only need IPv4 connectivity, explicitly bind to 0.0.0.0 to skip IPv6:

bash
# Bind only to IPv4
docker run -p 0.0.0.0:80:80 myimage

# In docker-compose.yml
services:
  web:
    ports:
      - "0.0.0.0:80:80"

This tells Docker to only create the IPv4 binding, which can avoid conflicts if another process is only using the IPv6 binding (or vice versa).

5Use a different host port

If you can't stop the conflicting process, map to a different host port:

bash
# Use port 8080 on the host instead of 80
docker run -p 8080:80 myimage

# In docker-compose.yml
services:
  web:
    ports:
      - "8080:80"

Then access your application at http://localhost:8080 instead of http://localhost:80.

6Clean up orphaned Docker resources

Sometimes stopped containers or stale network configurations hold ports:

bash
# Remove all stopped containers
docker container prune

# Remove unused networks (can release port bindings)
docker network prune

# If using docker-compose, clean up properly
docker-compose down

# Nuclear option: stop all containers and clean up
docker stop $(docker ps -aq)
docker container prune -f

Then restart the Docker daemon to ensure clean state:

bash
sudo systemctl restart docker
7Kill the specific docker-proxy process

If a stale docker-proxy is holding the port, find and kill it:

bash
# Find docker-proxy processes
ps aux | grep docker-proxy

# Find which one is using port 80
sudo lsof -i :80 | grep docker-proxy

# Kill the specific process (replace PID with actual number)
sudo kill <PID>

# If it won't die, force kill
sudo kill -9 <PID>

After killing stale proxies, restart Docker to ensure clean state.

Advanced notes

### Understanding IPv6 Binding in Docker

When you use -p 80:80, Docker creates bindings on both:
- 0.0.0.0:80 (IPv4, all interfaces)
- [::]:80 (IPv6, all interfaces)

The tcp6 socket with [::]: can actually accept both IPv4 and IPv6 connections due to IPv4-mapped IPv6 addresses. This is why a single tcp6 binding can block access even if you're only connecting via IPv4.

You can see this with docker ps:

bash
PORTS
0.0.0.0:80->80/tcp, :::80->80/tcp

### Binding to Specific Interfaces

To avoid conflicts, bind to specific IP addresses:

bash
# Only localhost (IPv4)
docker run -p 127.0.0.1:80:80 myimage

# Only localhost (IPv6)
docker run -p [::1]:80:80 myimage

# Specific network interface
docker run -p 192.168.1.100:80:80 myimage

### Disabling IPv6 in Docker

If you don't need IPv6 at all, you can disable it at the Docker daemon level:

json
// /etc/docker/daemon.json
{
  "ipv6": false
}

Then restart Docker: sudo systemctl restart docker

### Checking Port Availability Before Starting

Before running containers, verify port availability:

bash
# Check if port 80 is available
! (sudo lsof -i :80 > /dev/null 2>&1) && echo "Port 80 is free" || echo "Port 80 is in use"

# Or use netcat
nc -z localhost 80 && echo "Port 80 in use" || echo "Port 80 is free"

### systemd Socket Activation Conflicts

On modern Linux systems, systemd might activate sockets on-demand. Check for socket units:

bash
# List active socket units
systemctl list-units --type=socket

# Check if a specific port is managed by systemd
sudo ss -tlnp | grep systemd

If systemd is managing the port, you may need to disable the socket unit rather than just the service.

Frequently asked questions

What does "Error starting userland proxy: listen tcp6 [::]:80: bind: address alre" mean?
The "listen tcp6 [::]:80: bind: address already in use" error in Docker occurs when you try to start a container with port mapping, but the specified port is already occupied on the IPv6 network stack. 0) and IPv6 (::) addresses when you use port mapping like -p 80:80. The [::]: in the error message indicates Docker is trying to bind to all IPv6 interfaces on port 80.
How do I fix "Error starting userland proxy: listen tcp6 [::]:80: bind: address alre"?
The 'listen tcp6 bind: address already in use' error occurs when Docker attempts to bind a container port to an IPv6 address that's already occupied. Find and stop the conflicting process, bind to IPv4 only, or use a different port.
What causes "Error starting userland proxy: listen tcp6 [::]:80: bind: address alre"?
A web server (nginx, Apache, Caddy) is running on the host and binding to the same port Another Docker container is already using the same host port A system service started on boot before your Docker container
Is the "Error starting userland proxy: listen tcp6 [::]:80: bind: address alre" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading