Skip to content 99% OFF 🎉 Anniversary Sale 99% OFF Shared Hosting Use Code HURRYUP Claim Offer 99% OFF Hosting
99% OFF Hosting — Code HURRYUP
Products
AI Website Builder New VPS Hosting Cloud Servers Web Hosting cPanel Hosting Dedicated Servers Domains
Company
About Documentation Support Center Contact Get Started Call +91 75795 45488
Login
Hosting Panel — cPanel & Billing Console Panel — VPS Management
ALL SYSTEMS OPERATIONAL
VPS

Docker Filling Up Your VPS Disk? Full Cleanup Guide

Getwebup 6 min read

Your VPS was fine last month. Now df -h shows the root partition at 95% and you haven't deployed anything new. If you're running Docker, there's a good chance the daemon is quietly hoarding gigabytes in old image layers, dead containers, and log files that never get truncated. Here's where it actually goes and how to clean it up without taking a container down.

Symptom: disk fills up, but 'du' on your app folder looks fine

The giveaway is that regular disk-usage checks don't add up. You run du -sh /var/www or check your project folder and it's a few hundred MB, but df -h / says you're nearly out of space. That gap almost always means something outside your normal file tree is the culprit — and on a Docker host, that's /var/lib/docker.

You'll usually notice it one of these ways:

  • docker build or docker pull failing with no space left on device
  • A container that won't start, with logs mentioning a write failure
  • MySQL or another database container crashing mid-write
  • Deploys via docker compose up -d hanging or timing out

Confirm it's Docker before you go digging elsewhere:

df -h /
docker system df
docker system df -v

docker system df breaks usage down by images, containers, local volumes, and build cache — this is the fastest way to see which bucket is actually the problem instead of guessing.

Cause: where Docker actually puts your disk space

Docker doesn't delete anything by default. Every build, every pull, every stopped container leaves something behind on disk until you explicitly tell it to clean up.

Where it livesWhat's thereWhy it grows unnoticed
/var/lib/docker/overlay2Image layers and container writable layersOld image versions and dangling layers from every rebuild stay on disk after a new one replaces them
/var/lib/docker/containers/<id>/*.json.logContainer stdout/stderr logsThe default json-file log driver has no size cap unless you set one
/var/lib/docker/volumesNamed volumes (databases, uploads)Volumes from removed containers stick around unless you pass -v on removal
Build cacheLayers cached by docker build / BuildKitEvery CI run or local rebuild adds more, and it's rarely cleared

The single biggest offender on most VPS boxes we look at is unbounded container logs. A Node app that logs every request, running for six months without a size cap, can easily produce a multi-gigabyte log file that du -sh on your project won't ever show you.

Check log sizes directly

du -h $(docker inspect --format='{{.LogPath}}' $(docker ps -q)) 2>/dev/null | sort -rh

If one of these is several hundred MB or more, you've found a real chunk of your missing space.

Fix: clean up safely without breaking running containers

Don't reach for rm -rf /var/lib/docker — that nukes everything, including volumes with real data in them. Use Docker's own cleanup commands, which are safe by design: they never touch anything a running container or a named volume in use depends on.

1. Remove dangling images and stopped containers first

docker container prune -f
docker image prune -f

This clears exited containers and untagged (dangling) image layers — the safest cleanup, since nothing currently in use gets touched.

2. Remove unused images, not just dangling ones

If you've got old tagged versions sitting around from previous deploys (myapp:v1.2, myapp:v1.3, etc.), a plain prune won't remove them. Go further:

docker image prune -a -f

This removes every image not currently used by a running container. Fine on a production host where you deploy fresh images each release — just make sure nothing depends on pulling a cached older tag first.

3. Clear build cache

docker builder prune -f
# or, if disk space is critical:
docker builder prune -a -f

BuildKit's cache can be surprisingly large if you build images on the VPS itself rather than in CI. This is usually reclaimable with zero risk since it only affects future build speed, not anything running.

4. Volumes — be careful here

docker volume ls -f dangling=true
docker volume prune -f

Only run volume prune after checking the list it would remove. Named volumes from a docker compose down (without -v) are usually still attached to a compose project and won't show as dangling, but anonymous volumes from one-off docker run commands often are — and those can hold database data you actually want. When in doubt, list first, delete individually.

5. The one-liner, once you trust it

docker system prune -a --volumes -f

This is the nuclear option: dangling and unused images, stopped containers, unused networks, and unused volumes, all in one pass. Run the individual commands above first a few times so you know what's actually being removed before you trust this one on a production box.

Stop logs from refilling the disk

Cleanup only buys you time if nothing's capping log growth. Set a size limit on the default logging driver in /etc/docker/daemon.json:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
sudo systemctl restart docker

This caps each container's log at 10MB across 3 rotated files (30MB max per container) instead of growing forever. One catch: this only applies to new containers created after the restart — existing containers keep their old, uncapped log driver until you recreate them (docker compose up -d --force-recreate does it cleanly).

Prevention: keep it from creeping back up

  • Automate cleanup on a schedule. A weekly cron running docker system prune -f (skip -a in automation unless you're confident nothing needs those cached images) keeps dangling layers from accumulating between manual checks.
  • Set the log cap in daemon.json before you deploy your first container, not after you hit 100% disk.
  • Use multi-stage builds so your final images don't carry build tools and intermediate layers that never get used at runtime.
  • Watch docker system df alongside df -h in your monitoring, not just root partition usage — it tells you which bucket is growing before it becomes an emergency.
  • Tag and prune deliberately. If your CI/CD pushes a new image tag on every commit, add a retention policy (keep last 5, delete older) instead of letting tags accumulate indefinitely.

Once the log driver is capped and a prune job runs weekly, Docker's disk footprint on a VPS stays predictable instead of creeping up until something crashes.

Frequently asked questions

Is it safe to run 'docker system prune -a --volumes' on a production server?

Run the individual prune commands (container, image, builder) first so you can see exactly what gets removed. Volume pruning is the riskiest part — always run 'docker volume ls -f dangling=true' first and check the list before deleting, since a volume you think is unused might still hold data from a container that isn't currently running.

Why does 'du -sh' on my project folder not show the disk usage Docker is using?

Docker stores images, containers, and volumes under /var/lib/docker, completely separate from your application code. Checking your project directory will never reveal Docker's disk usage — use 'docker system df' instead to see usage broken down by images, containers, volumes, and build cache.

I set the log size limit in daemon.json but my old container's log is still huge. Why?

The log-opts setting in daemon.json only applies to containers created after you restart Docker. Existing containers keep using whatever log driver settings they were started with. Recreate the container (docker compose up -d --force-recreate, or docker rm and docker run again) to pick up the new limit.

Will 'docker image prune -a' delete images I still need?

No — it only removes images that aren't referenced by any container, running or stopped. If an image is currently in use, or a stopped container still references it, it stays. The risk is losing a cached older tag you might want to roll back to quickly, since prune doesn't know about your deployment history, only what's currently attached to a container.

How often should I run Docker cleanup on a VPS?

A weekly cron job with 'docker container prune -f' and 'docker image prune -f' is enough for most single-app VPS setups. If you build images directly on the server or deploy multiple times a day, run it more often, or add 'docker builder prune -f' to the same job since build cache grows fastest on frequent rebuilds.

#docker #disk-space #vps #docker-prune #overlay2 #container-logs

Keep reading

Chat with Support