There's no docker stop all. There wasn't one when I first wrote this post in 2020, and Docker 28 still doesn't have it. docker stop --help offers a signal and a timeout, and that's the whole menu. (Podman, for what it's worth, has podman stop --all.)
The command you actually want is:
docker stop $(docker ps -q) If you want to know why it works, why it sometimes throws an error, and why some containers come back from the dead afterwards, read on.
Why you'd want this
Sometimes you start containers from your IDE and forget to stop them before switching projects. Or maybe you're done with your work (you lucky, you!) and don't want to waste memory or CPU cycles on services you aren't using. Either way, something is hogging the ports you need, eating your RAM and battery, and the IDE that started it all is long gone. Time for the terminal.
Let's see what we're up against. What does docker ps say?
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9c07b6375e0e my_project_tunnel "/bin/sh -c 'rm -rf …" 4 weeks ago Up 3 seconds 0.0.0.0:8062->8062/tcp my_project_tunnel_1
91b757beda05 my_project_web "docker-php-entrypoi…" 4 weeks ago Up 2 seconds 0.0.0.0:8000->80/tcp my_project_web_1
245f7e35f4f3 mysql:5.7 "docker-entrypoint.s…" 3 months ago Up 3 seconds 0.0.0.0:3306->3306/tcp, 33060/tcp my_project_db_1
77bc948bb148 mailhog/mailhog "MailHog" 3 months ago Up 3 seconds 0.0.0.0:1025->1025/tcp, 0.0.0.0:8025->8025/tcp my_project_mailhog_1 Four containers. Docker's answer, out of the box, is four separate commands:
$ docker stop 9c07b6375e0e
$ docker stop 91b757beda05
$ docker stop 245f7e35f4f3
$ docker stop 77bc948bb148 Quite a mouthful. You can shave it down by typing only the first few characters of each container ID, but the real fix is to make the shell do the work: run docker ps, grab the container IDs, and feed them straight into docker stop.
Step 1: Get the running container IDs
Run docker ps with the -q flag and it returns only container IDs. Look!
$ docker ps -q
9c07b6375e0e
91b757beda05
245f7e35f4f3
77bc948bb148 Many tutorials will tell you to add the -a flag, making the full command docker ps -aq. Here, -a is redundant. According to the docker ps documentation, omitting -a returns only running containers, which is exactly what we need. Stopped containers don't need stopping.
Step 2: Feed them to docker stop
Almost every shell lets you run a command in a subshell, capture its output, and use it as arguments for another command. This syntax works in bash and zsh, and PowerShell happens to accept it too:
docker stop $(docker ps -q) This works in fish:
docker stop (docker ps -q) And if you're stuck in the old Windows cmd, it's a loop:
FOR /f "tokens=*" %i IN ('docker ps -q') DO docker stop %i "docker stop" requires at least 1 argument
Run the one-liner when nothing is running and Docker complains:
$ docker stop $(docker ps -q)
docker: 'docker stop' requires at least 1 argument
Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...]
See 'docker stop --help' for more information Older versions word it as "docker stop" requires at least 1 argument. and mean the same thing. Nothing is broken. docker ps -q printed an empty list, the shell substituted it with nothing, and Docker got a bare docker stop.
On your own terminal that's just noise. In a script it's a real problem, because the exit code is 1, and anything running under set -e or in a CI job dies right there, on the one occasion there was nothing to clean up.
The version that stays quiet:
docker ps -q | xargs -r docker stop -r tells GNU xargs not to run the command when the input is empty. The xargs that ships with macOS never runs on empty input anyway, and it accepts -r without complaint, so the same line is safe on both.
Stopping only some of them
"All" is often more than you meant. I usually have two or three Compose projects up, and I want to take down the one hogging port 3306, not everything. docker ps takes filters, and they combine nicely with -q:
# everything from one Compose project
docker stop $(docker ps -q --filter label=com.docker.compose.project=my_project)
# containers whose name contains a string
docker stop $(docker ps -q --filter name=my_project)
# everything started from one image
docker stop $(docker ps -q --filter ancestor=mysql:8) Not sure what your projects are called? docker compose ls lists them, along with the compose files they came from.
docker compose stop does the same job as the first command, but only when you're standing in the project's directory. The label filter works from anywhere, which matters when the project in question is the one you forgot about.
Why it sometimes takes ten seconds
docker stop sends SIGTERM, waits for the process to exit, and sends SIGKILL if it's still there after 10 seconds. A well-behaved service is gone in a moment. A container whose main process ignores SIGTERM (a shell script as PID 1 is the usual suspect) sits there for the full 10 seconds.
The good news is that Docker doesn't queue them up. I started three containers that ignore SIGTERM and stopped them with the one-liner on Docker 28.2.2. The whole thing took 10.2 seconds, not 30.
If you don't care about a clean shutdown, shorten the wait or skip it:
docker stop -t 2 $(docker ps -q)
docker kill $(docker ps -q) Not every service appreciates being killed. Databases in particular would rather get a polite stop and a chance to flush to disk. If the containers are throwaway dev services, kill away.
Containers that come back
You stop everything, reboot, and half of it is running again.
That's the restart policy. A container started with restart: always stays down after a manual stop only until the Docker daemon restarts. After a reboot, or after Docker Desktop updates itself, it's back. unless-stopped is the polite sibling: stop it by hand and it stays stopped.
To see who has which policy:
docker inspect --format '{{.Name}} {{.HostConfig.RestartPolicy.Name}}' $(docker ps -q) And to switch it off for everything that's currently running, before you stop it:
docker update --restart=no $(docker ps -q) If the policy comes from a docker-compose.yml, the next docker compose up that recreates the container sets it again, so fix it there too.
Make it a command
If you do this more than twice a week, put it in your .bashrc or .zshrc:
dstop() {
docker ps -q "$@" | xargs -r docker stop
} dstop stops everything, and dstop --filter name=my_project stops a subset, because the arguments pass straight through to docker ps. It goes through xargs rather than a variable on purpose: zsh doesn't split an unquoted variable on newlines, so the obvious docker stop $ids hands Docker one long, invalid container name.
Takeaway
Six years on, the missing docker stop --all is still a subshell away. Learn the docker ps -q half and you get the rest for free: the same trick feeds docker kill, docker update and docker inspect.
