Kill Process Using a Specific Port on Linux
Freeing up a port that's already in use on Linux is a two-step process: first identify exactly which process is holding it, then kill that specific process — guessing or killing the wrong process can interrupt something unrelated.
The Problem
You try to start an application, and it fails because the port it needs is already occupied:
Error: listen EADDRINUSE: address already in use :::3000
bind: address already in use
Something else on the machine is already using that port, but it's not always obvious what, especially if it was started a while ago or by a different tool entirely.
Why It Happens
This isn't really a bug — it's the operating system correctly preventing two processes from listening on the same port simultaneously. It usually happens because:
- A previous instance of the same application is still running, often from a crashed process that didn't clean up properly, or a background process you forgot was still active
- A different, unrelated service happens to be using the same default port (common with default ports like 3000, 5432, 8080 that many tools use out of the box)
- A Docker container is mapped to that port and still running, even though you're trying to run something else directly on the host using the same port
The Fix
First, identify what's using the port. The lsof command gives a clear, direct answer:
lsof -i :3000
This shows the process name, PID, and user for anything listening on port 3000. If lsof isn't installed, ss is available on virtually every modern Linux system by default and gives similar information:
ss -ltnp | grep :3000
Once you have the PID from either command, kill that specific process:
kill <PID>
If the process doesn't respond to a normal kill (some processes ignore the default termination signal), force it with SIGKILL:
kill -9 <PID>
For a faster one-line approach that combines identifying and killing in a single command, fuser handles both steps together:
fuser -k 3000/tcp
This finds and kills whatever is using port 3000 over TCP without needing to manually extract and pass a PID.
If the process using the port turns out to be a Docker container rather than a regular process, killing the underlying process directly usually isn't the right approach — stop the container properly instead:
docker ps
docker stop <container_id_or_name>
Still Not Working?
If lsof or ss show nothing using the port, but the application still reports it as in use, the port may be stuck in a TIME_WAIT state from a recently closed connection rather than genuinely being held by an active process — this is normal TCP behavior and typically resolves itself within a minute or two without any action needed. Confirm this by checking the connection state directly:
ss -tan | grep :3000
A state of TIME_WAIT here confirms it's a transient socket cleanup delay, not a genuinely occupied port, and waiting briefly (or restarting the application with SO_REUSEADDR enabled, if you control the code) resolves it without needing to kill anything.
It's also worth checking whether the process is running inside a container network namespace rather than directly on the host, since lsof and ss run on the host only see host-level sockets by default. A port published from inside a container (via Docker's -p flag) shows up as being held by the Docker proxy process on the host, which is expected — but a port used only internally within a container's own network, without being published, won't be visible from host-level tools at all, even though it might still conflict with something else running inside that same container's network namespace.
If you regularly run into port conflicts during local development, consider adopting a small habit: checking for an existing process before starting a new one, rather than discovering the conflict only after the start command fails:
lsof -i :3000 || echo "Port 3000 is free"
Wrapping this into a short shell function or alias saves the repeated cycle of hitting the error, then manually running the diagnostic commands separately each time.