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 addressFind Which Process Uses a Port
Use any of these commands to identify the process occupying a port:
Using ss (Modern, Recommended)
# Find process using port 80
sudo ss -tlnp | grep :80Sample output:
LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1234,fd=6))Using lsof
sudo lsof -i :80Sample output:
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
nginx 1234 root 6u IPv4 25678 TCP *:http (LISTEN)Using fuser
sudo fuser 80/tcpResolve 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 :80Kill 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 1234Docker 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 containersSolution 2: Change Port in docker-compose.yml
services:
web:
ports:
- "8080:80" # Use 8080 instead of 80Then restart:
docker-compose down
docker-compose up -dCommon 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 neededPort 3306 (MySQL)
sudo systemctl stop mysql
# or
sudo systemctl stop mariadbPort 5432 (PostgreSQL)
sudo systemctl stop postgresqlPort 6379 (Redis)
sudo systemctl stop redis-serverTCP 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=1Make permanent by editing /etc/sysctl.conf:
echo "net.ipv4.tcp_tw_reuse = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -pChange 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 nginxVerify Port is Now Free
sudo ss -tlnp | grep :80
# Should return empty if port is freePrevention: Check Available Ports
List all listening ports:
sudo ss -tlnp
# or traditional netstat
netstat -tlnpPlan 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>