Common Issues

Port Already in Use

Fix 'Address already in use' errors, find which process is using a port and free it or reconfigure your service

The "Address already in use" error occurs when you try to start a service on a port that's already occupied by another process. This guide shows you how to identify and resolve the conflict.


Identify the Problem

Common Error Messages

bind: address already in use
listen tcp :80: bind: address already in use
Cannot assign requested address

Find Which Process Uses a Port

Use any of these commands to identify the process occupying a port:

# Find process using port 80
sudo ss -tlnp | grep :80

Sample output:

LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1234,fd=6))

Using lsof

sudo lsof -i :80

Sample output:

COMMAND  PID USER FD TYPE DEVICE SIZE NODE NAME
nginx   1234 root 6u IPv4  25678      TCP *:http (LISTEN)

Using fuser

sudo fuser 80/tcp

Resolve the Conflict

Stop the Conflicting Service

Once you've identified the process (e.g., Nginx PID 1234):

# Stop the service
sudo systemctl stop nginx

# Verify it's stopped
sudo ss -tlnp | grep :80

Kill a Process (Last Resort)

Only use if service won't stop normally:

# Graceful kill
kill -15 1234

# Force kill (dangerous, can cause data loss)
kill -9 1234

Docker Port Conflicts

Check Docker Containers Using a Port

docker ps | grep 80
docker inspect <container_id> --format='{{json .HostConfig.PortBindings}}' | jq .

Solution 1: Stop the Container

docker stop <container_id>
docker container prune  # Remove stopped containers

Solution 2: Change Port in docker-compose.yml

services:
  web:
    ports:
      - "8080:80"  # Use 8080 instead of 80

Then restart:

docker-compose down
docker-compose up -d

Common Services Blocking Ports

Port 80 / 443 (HTTP / HTTPS)

Usually occupied by Nginx, Apache, or other web servers:

# Stop Nginx
sudo systemctl stop nginx

# Check if it runs on boot
sudo systemctl status nginx
sudo systemctl disable nginx  # Disable auto-start if needed

Port 3306 (MySQL)

sudo systemctl stop mysql
# or
sudo systemctl stop mariadb

Port 5432 (PostgreSQL)

sudo systemctl stop postgresql

Port 6379 (Redis)

sudo systemctl stop redis-server

TCP TIME_WAIT State

After closing a connection, the port enters TIME_WAIT state for ~60 seconds before becoming available again.

Quick Fix: SO_REUSEADDR

Enable address reuse in your kernel:

sudo sysctl -w net.ipv4.tcp_tw_reuse=1

Make permanent by editing /etc/sysctl.conf:

echo "net.ipv4.tcp_tw_reuse = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Change Service Port

If you need to run two services, change one to a different port.

Example: Move Nginx from 80 to 8080

Edit /etc/nginx/sites-available/default:

server {
    listen 8080 default_server;
    listen [::]:8080 default_server;

    server_name _;

    location / {
        # ... your config
    }
}

Test and restart:

sudo nginx -t
sudo systemctl restart nginx

# Verify it's listening on 8080
sudo ss -tlnp | grep nginx

Verify Port is Now Free

sudo ss -tlnp | grep :80

# Should return empty if port is free

Prevention: Check Available Ports

List all listening ports:

sudo ss -tlnp

# or traditional netstat
netstat -tlnp

Plan port usage to avoid conflicts in advance.

ss -tlnp is the modern equivalent to netstat -tlnp. Use ss on newer Linux systems for better performance.


Troubleshooting Checklist

  • Identify process: sudo ss -tlnp | grep :80
  • Stop conflicting service: sudo systemctl stop <service>
  • Verify port is free: sudo ss -tlnp | grep :80 (should be empty)
  • Start your service: sudo systemctl start <your-service>
  • Test connection: curl http://localhost:80
  • Enable auto-start if needed: sudo systemctl enable <your-service>

On this page