# How to Fix Docker No Space Left on Device (7 Steps)

> Cara mengatasi no space left on device docker step by step: read docker system df, prune safely, keep the newest images, cap logs and the journal.

URL: https://www.matthewswong.com/en/blog/cara-mengatasi-docker-no-space-left-on-device/

- Author: Matthews Wong (https://www.matthewswong.com/en/about/)
- Published: 2026-10-17
- Updated: 2026-10-17
- Category: DevOps

> **Key takeaway:** To fix no space left on device in Docker, first measure with df -h, docker system df and journalctl --disk-usage. Then prune old images and build cache with an until filter, keep only the newest images, cap container logs with max-size and max-file, vacuum the journal, and never prune volumes automatically.

The error shows up at the worst moment: in the middle of a docker pull or a build, with a deploy half done. You run the command again, it fails again, and the first instinct is to paste a prune command from a forum and hope. Some of those commands delete data that cannot be pulled back.

This guide goes in a safer order: look first, delete second. Seven steps, each with commands and what to expect. The cleanup commands come from Docker's own documentation, and the retention and log settings are the ones this site's deploy workflow and compose file use.

Want the concepts behind the commands, with an interactive explainer and a quiz? Read the free lesson

Docker No Space Left on Device: Find What Fills the Disk

. This post is the hands-on walkthrough.

## What you need

You need three things before you start. Read them, because the whole approach depends on measuring before deleting.

- A Linux server with Docker installed and shell access, ideally with sudo.
- systemd on that server, so journalctl exists. Most mainstream distributions use it.
- Five minutes to read each output before running the next command.

Every path and hostname below is a placeholder, such as ghcr.io/example/myapp. Replace them with your own. If the server is production, do the measuring steps first and the deleting steps only once you know what you are removing.

## Step 1: Confirm the disk is really full

Run df -h on the filesystem that holds Docker's data. A Use% near 100 percent confirms the error, and the number gives you a baseline to compare with after the cleanup. If the disk is not full, the problem is somewhere else and no prune will help.

This site's deploy workflow prints df -h before and after each cleanup step for the same reason. The log then shows how much space each step actually bought, and a step that did nothing is visible instead of hidden behind a success message.

## Step 2: See what Docker itself is using

docker system df shows how much disk the Docker daemon uses, in rows for images, containers and local volumes. The RECLAIMABLE column estimates what you could free. Add -v to get one line per image, container and volume, including the unique size an image alone uses and the size it shares with other images.

Look for the biggest line. Many images with 0 containers means old releases piling up. A large volume means application data, which is not yours to prune. The numbers differ on every machine, so read your own output instead of guessing from someone else's.

## Step 3: Check the journal and the big folders

Docker's numbers do not include the systemd journal. journalctl --disk-usage reports the total of all archived and active journal files. If Docker's own total is small but the disk is full, the du listing helps you find the folder that holds the rest.

Container logs are a quiet culprit too. The json-file driver keeps a single log file per container by default and never rotates it until you set max-size. No prune command touches those files, which is why step 6 is a setting and not a cleanup.

## Step 4: Prune safely, with an age filter

A plain docker image prune only removes dangling images: untagged and not used by any container. Images from every deploy carry a tag, so they survive. Adding -a widens it to every image no container uses, and --filter until=72h limits it to items older than 72 hours. Build cache takes the same until filter through docker builder prune.

Read the confirmation prompt every time. The pruning documentation is explicit about two things: each command asks before deleting unless you pass -f, and volumes are never removed automatically because that could destroy data. That second sentence is why the Right version above never mentions volumes.

> docker volume prune removes unused anonymous volumes, docker volume prune --all also removes unused named volumes, and docker system prune --volumes adds anonymous volumes to a system prune. A volume that no container references right now can still hold a database. Do not put any volume command in a cleanup script, and do not paste one from a forum without reading it.

## Step 5: Keep only the newest images

An age filter assumes a steady pace of deploys. This site's deploy workflow had one until 19 deploys landed in 40 hours: every image was younger than 72 hours, the prune removed nothing, and the disk reached 93 percent. The fix was a count cap beside the age filter. The script above lists the app's images newest first, skips the first two, and removes the rest.

Two properties make this safe. docker image rm cannot remove an image used by a running container unless you add -f, so never add -f here and the live release survives. And removing an image from the host does not delete it from the registry, so an older release can be pulled again. The two newest images are the running one and the one a rollback needs.

## Step 6: Cap container logs so it cannot happen again

The json-file driver defaults to max-size of -1, which is unlimited, and max-file of 1, which only takes effect when max-size is also set. This site's compose file sets 10m and 3, so each container keeps at most three log files of up to 10 MB. For every new container on the host, put the same options in /etc/docker/daemon.json and restart Docker.

One catch from the Docker docs: existing containers do not pick up the new logging configuration automatically. A container started before you changed the setting keeps its old behaviour until you recreate it. After recreating, the log of that container rotates and stops growing without limit.

## Step 7: Vacuum the journal and set a limit

journalctl --vacuum-size removes the oldest archived journal files until they fit under the size you give. It only deletes archived files, while --disk-usage counts active ones too, so the total can stay above your target. That is expected. To keep the journal bounded permanently, set SystemMaxUse in the Journal section of a drop-in file under /etc/systemd/journald.conf.d/.

After editing journald.conf, restart the systemd-journald service. The man page documents the option and its file locations but does not describe how to apply a change, so check your distribution's documentation for that step. Use the vacuum to recover space now and the setting to stop the problem coming back.

## Common errors and how to fix them

These are the failures that make a cleanup look successful while the disk stays full, or that turn it into an incident.

| Symptom | Cause | Fix |
| --- | --- | --- |
| docker image prune finishes but the disk is still full | Plain prune only removes dangling images, and deployed images are tagged | Add -a with an until filter, then cap by count (steps 4 and 5) |
| until=72h reports nothing reclaimed on a busy day | Many deploys landed inside the window, so no image is older than 72 hours | Add the newest-N cap from step 5 and print df afterwards |
| A container log keeps growing and no prune touches it | max-size is unlimited by default, or only max-file was set | Set both max-size and max-file, then recreate the container |
| Journal still above the vacuum target | The vacuum deletes archived files only, and the active file counts too | Treat it as normal, and set SystemMaxUse for a lasting limit |
| A database lost its data after a cleanup | A volume prune or system prune --volumes removed a volume no container referenced | Restore from backup, and remove every volume command from cleanup scripts |
| A rollback is slow or fails after a cleanup | prune -a with no filter removed the previous release, which no container uses | Keep the newest two images, and pull the older tag from the registry if needed |

## Checklist

I ran df -h, docker system df and journalctl --disk-usage before deleting anything.

Image and build cache cleanup uses an until filter, not a bare prune -a.

The newest two images are kept, and docker image rm never runs with -f.

Every container sets both max-size and max-file, and old containers were recreated.

No volume command appears in any script, and the journal has a SystemMaxUse limit.

## Learn more

To see how these pieces fit together, with a diagram you can step through and three quiz questions, read the lesson

. For keeping the images themselves smaller, which also slows how fast the disk fills, see

.

The rule to carry: measure first, prune by age and by count, cap what grows by itself, and leave volumes alone. A disk that fills once will fill again, so the settings in steps 5 to 7 matter more than the one-off cleanup.

## Sources and further reading

- Docker docs: Prune unused Docker objects
- Docker docs: docker system df
- Docker docs: JSON File logging driver
- man page: journalctl (--disk-usage, --vacuum-size)
- man page: journald.conf (SystemMaxUse)

## Source links

- https://docs.docker.com/engine/manage-resources/pruning/
- https://docs.docker.com/reference/cli/docker/system/df/
- https://docs.docker.com/engine/logging/drivers/json-file/
- https://man7.org/linux/man-pages/man1/journalctl.1.html
- https://man7.org/linux/man-pages/man5/journald.conf.5.html

## FAQ

### Why does Docker say no space left on device?

The filesystem that holds Docker's data is full. The usual causes are tagged images from every deploy, build cache, container logs with no size limit, and the systemd journal. Run df -h and docker system df to see which one it is before you delete anything.

### Is docker system prune safe to run?

A plain docker system prune removes stopped containers, unused networks, dangling images and unused build cache, and it leaves volumes alone. Adding -a also removes every unused image, including the previous release you might roll back to, and adding --volumes removes unused anonymous volumes. Read the confirmation prompt and prefer an until filter.

### Will docker volume prune delete my database?

It can. docker volume prune removes unused anonymous volumes, and --all also removes unused named volumes. A volume that no container references at that moment still counts as unused, even if it holds a database, so keep volume commands out of cleanup scripts.

### How do I stop Docker logs from filling the disk?

Set both max-size and max-file for the json-file logging driver, for example 10m and 3. max-size defaults to unlimited and max-file only works when max-size is set. Existing containers keep their old logging until you recreate them.

### Why is the disk still full after docker image prune?

A plain image prune only removes dangling images, meaning untagged and unused ones, while images from deploys are tagged. Use -a with an until filter, and cap the number of images you keep. Also check logs and the journal, because image prune never touches them.

---

- HTML version: https://www.matthewswong.com/en/blog/cara-mengatasi-docker-no-space-left-on-device/
- Bahasa Indonesia: https://www.matthewswong.com/id/blog/cara-mengatasi-docker-no-space-left-on-device/
- Site index for agents: https://www.matthewswong.com/llms.txt
- Sitemap: https://www.matthewswong.com/sitemap.xml
- API description (OpenAPI): https://www.matthewswong.com/openapi.json
