List, stop, and remove containers
Learn to list running/stopped containers, stop them gracefully, and remove them to keep your Docker environment clean. Includes practical commands, common flags, and troubleshooting.
Focus: list, stop, and remove containers
If you've been running Docker containers in your local environment for a while, a handful of active containers can quickly turn into dozens of orphaned, stopped, or unused ones. Without knowing how to list, stop, and remove containers efficiently, your disk fills up, port collisions happen, and docker ps becomes a wall of noise. These three operations — listing, stopping, and removing — form the backbone of container lifecycle management and keep your development environment fast, clean, and predictable.
The problem this lesson solves
Docker doesn't automatically clean up after itself. Every time you run docker run, you leave behind a stopped container in the "Exited" state unless you explicitly remove it with --rm. After a few days of experimentation, you may see this familiar output:
docker ps -a
CONTAINER ID IMAGE STATUS PORTS NAMES
b3f23a... nginx:latest Exited (0) 2 days ago webserver-old
c7d89e... python:3.10-slim Exited (137) 4 hours ago py-app
f2a1c2... postgres:14 Exited (0) 1 week ago pg-test
That's wasted resources — disk space for the container's writable layer, and mental overhead when you need to find the one container that's actually running.
The root cause? Beginners often know docker run but don't learn the complementary commands. They restart their machine, lose track, or worse — accumulate hundreds of anonymous containers until Docker screams about insufficient disk space.
After this lesson, you'll be able to: - See exactly what containers exist (running and stopped) - Stop one or all running containers without guessing - Permanently remove containers you no longer need
Core concept / mental model
Think of a Docker container like a lightweight disposable laptop. When you create one (docker run), you power it on. When you're done, you should shut it down (docker stop), and then either recycle or throw it away (docker rm). If you just walk away, the laptop stays on (container keeps running) or sits in a powered-off state on your shelf (stopped but still consuming disk space).
Key definitions
- Running container: Active process that uses CPU, memory, and possibly ports. Listed by
docker pswithout flags. - Stopped container: Exited process. Still consumes finite disk space (about 10–100 MB per container) and retains its filesystem state. Listed by
docker ps -a. - Removed container: Deleted permanently. Cannot be restarted — you must recreate it from an image.
The three-command pipeline
List → Stop (if running) → Remove
Each command has a clear purpose:
1. docker ps — discover what's out there.
2. docker stop — gracefully terminate the main process (SIGTERM, then SIGKILL after timeout).
3. docker rm — delete the container metadata and writable layer from disk.
Pro tip: If you skip
stopand rundocker rm -f, Docker sends SIGKILL immediately. This can corrupt stateful apps (databases, file writers). Always preferstopthenrmfor production-like containers.
How it works step by step
The practical flow is a three-step loop:
Step 1 — List all containers
# Running only
docker ps
# All containers (running + stopped)
docker ps -a
# Quiet mode — show only container IDs
docker ps -aq
The -a flag (or --all) is the most common way to see stopped containers. Without it, you only see active ones — this is why beginners often think "my container disappeared" when in reality it just stopped.
Step 2 — Stop a running container
docker stop <container-id-or-name>
Docker sends a SIGTERM signal to the main process (PID 1 inside the container). By default, it waits 10 seconds for graceful shutdown. If the application doesn't exit in time, Docker sends SIGKILL.
You can also use:
- docker stop -t 30 my-container — wait 30 seconds before killing.
- docker kill my-container — immediate force stop (no grace period).
Step 3 — Remove a stopped container
docker rm <container-id-or-name>
If the container is still running, docker rm fails with:
Error response from daemon: You cannot remove a running container ...
Combine stop and remove in one line for convenience:
docker stop my-container && docker rm my-container
Or skip the stop entirely with force-remove:
docker rm -f my-container
Hands-on walkthrough
Let's create, list, stop, and remove containers together.
Setup — create two test containers
Run these commands to generate some containers to work with:
# Run an Nginx container in the background
docker run -d --name demo-nginx -p 8080:80 nginx:alpine
# Run a quick echo container that exits immediately
docker run --name demo-echo alpine echo "Hello from Docker"
Now list everything:
docker ps
docker ps -a
Expected output:
- docker ps shows demo-nginx running (STATUS: Up ...).
- docker ps -a shows both demo-nginx (Up) and demo-echo (Exited (0) ...).
Stop the running container
docker stop demo-nginx
Verify it stopped:
docker ps -a | grep demo-nginx
# Output: CONTAINER ... Exited (0) ...
Both containers are now stopped.
Remove both containers
docker rm demo-nginx demo-echo
Check that they're gone:
docker ps -a | grep demo-
# No output — containers are removed
Clean up all stopped containers at once
For daily housekeeping, this one-liner is gold:
docker container prune
It prompts for confirmation. To skip the prompt:
docker container prune -f
Warning:
pruneremoves all stopped containers. Use it only when you're sure you don't need them anymore.
Remove all containers (running and stopped)
This is a power-user trick — use with care.
# Stop all running containers
docker stop $(docker ps -q)
# Remove all containers (now all stopped)
docker rm $(docker ps -aq)
Or in one line:
docker rm -f $(docker ps -aq)
This sends SIGKILL to everything. Great for a fresh start, but avoid on systems with stateful databases.
Compare options / when to choose what
| Scenario | Command | Why |
|---|---|---|
| Stop a single container gracefully | docker stop <name> |
Sends SIGTERM; app can flush data |
| Stop immediately (force) | docker kill <name> |
Sends SIGKILL; no cleanup chance |
| Remove a single stopped container | docker rm <name> |
Removes only that one |
| Remove a running container (force) | docker rm -f <name> |
Stops and removes in one command |
| Remove all stopped containers | docker container prune |
Safest bulk cleanup |
| Remove all containers (running+stopped) | docker rm -f $(docker ps -aq) |
Nuclear option — only for dev/test |
When in doubt, prefer the safe dance:
1. docker ps -a
2. docker stop <specific containers>
3. docker rm <specific containers>
Troubleshooting & edge cases
"Cannot remove container: is running"
Cause: You tried docker rm on a running container.
Fix: Either stop first (docker stop then docker rm) or use force (docker rm -f).
Container disappears after docker run
Cause: You used the --rm flag when running. Example: docker run --rm alpine echo hi
Solution: The container is automatically removed on exit. This is intentional — use it when you don't need the container after it stops.
docker ps -a shows no output even though you just ran a container
Cause 1: You forgot the -a flag. Run docker ps -a (not docker ps).
Cause 2: The container exited and was created with --rm. It's gone forever.
Cause 3: The container was already removed with docker rm or prune.
What about containers that fail to stop?
Some containers ignore SIGTERM and stay alive. Try:
- docker kill <name> — immediate SIGKILL.
- Check if the container has custom PID 1 behavior (e.g., tini, s6).
For stubborn containers:
docker kill <name> # if stop doesn't work
docker rm -f <name> # if even kill seems stuck (rare)
Large number of containers make prune slow
docker container prune can take time if you have hundreds of containers with large writable layers. Consider removing them in batches:
docker rm $(docker ps -aq --filter "status=exited" --filter "status=created")
What you learned & what's next
You now know the core lifecycle commands:
- List containers with docker ps (running) and docker ps -a (all)
- Stop gracefully with docker stop or forcefully with docker kill
- Remove with docker rm, docker rm -f, or docker container prune
You can confidently manage container clutter and keep your development environment lean.
What's next? In the next lesson, you'll learn how to inspect and view logs of running containers — essential for debugging why your app crashes after a container restart. You'll use docker logs, docker inspect, and docker exec to dive inside the container and see what's really happening.
Until then, practice the safe dance: list, stop, then remove. Your hard drive will thank you.
Practice recap
Run docker run -d --name test-practice nginx:alpine, then list your containers. Stop the container with docker stop test-practice, verify it stopped, then remove it with docker rm test-practice. Finally, run docker ps -a to confirm it's gone. Repeat this cycle three times until the commands feel automatic.
Common mistakes
- Running
docker rmon a running container and getting an error — always stop first, or usedocker rm -f. - Forgetting the
-aflag and thinking containers vanished — always usedocker ps -ato see stopped containers. - Using
docker container prunewithout noticing that it removes ALL stopped containers, including ones you may need later. - Assuming
docker stopis instant — it waits 10 seconds by default; usedocker killfor immediate termination. - Using
docker rm -fon a database container — this causes data loss since it sends SIGKILL without a graceful shutdown.
Variations
- Use
docker kill <name>instead ofdocker stopwhen you need immediate termination without grace period. - Use
docker rm -v <name>to also remove the container's anonymous volumes — useful for cleaning up database containers. - Use
docker container listas an alternative todocker ps— some CI scripts prefer the long-form command for clarity.
Real-world use cases
- Cleaning up dev containers after a spike in experimentation — use
docker container pruneto reclaim disk space. - Hot-swapping a service in a multi-container app — stop the old container, then start the new one with the same port mapping.
- CI/CD pipeline cleanup — in a runner, stop and remove all containers to ensure a clean state before each job.
Key takeaways
docker psshows running containers;docker ps -ashows all (including stopped).- Always
docker stopbeforedocker rmfor graceful shutdown — usedocker rm -fonly in emergencies. docker container pruneremoves all stopped containers at once — use with caution.- Combine stop and remove with
docker stop <name> && docker rm <name>for controlled cleanup. - The
--rmflag ondocker runautomatically removes the container when it stops — ideal for short-lived tasks.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.