A stopped container still exists until you remove it

docker ps lists what is running, and after a fortnight of experiments it looks reassuringly short. The container that exited is not gone — its writable layer, its logs and its configuration are all still under /var/lib/docker. The only thing that changed is that it stopped appearing in the default listing.

docker ps            # running only
docker ps -a         # everything ever created, Exited (0) included

docker rm -v 3f2b9c1a4e7d      # -v also removes the volumes it created

# the sweep: rm refuses containers that are still running, so this is
# noisier than it is dangerous
docker rm $(docker ps -a -q)

# untagged images left behind by rebuilds that reused a tag
docker images | grep '^<none>'

du -sh /var/lib/docker

Each stopped container keeps its own copy-on-write layer, holding everything written since it started — a container that ran composer install and exited is carrying a vendor directory around. The logs are worse over time: the JSON log file grows without a limit and is only deleted with the container. Anonymous volumes are the part that leaks silently, because docker rm without -v leaves a directory under /var/lib/docker with nothing referring to it and no command to find it again. Getting into the habit of docker run --rm for anything interactive removes most of the problem at source. The other half is images: every rebuild that reuses a tag leaves the previous one behind as <none>, still holding its layers on disk.