{"id":46,"date":"2026-07-31T22:52:19","date_gmt":"2026-07-31T19:52:19","guid":{"rendered":"https:\/\/john-nessime.com\/blog\/?p=46"},"modified":"2026-07-31T22:52:21","modified_gmt":"2026-07-31T19:52:21","slug":"docker-disk-usage-cleanup","status":"publish","type":"post","link":"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/","title":{"rendered":"Cleaning Up Docker Disk Usage Safely"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">The alert says the root partition is at 97%. You SSH in, run <code>df -h<\/code>, and <code>\/var\/lib\/docker<\/code> is sitting on forty-something gigabytes. The first search result tells you to run <code>docker system prune -a --volumes<\/code>, and it will absolutely free the space. It will also delete the volume holding your Postgres data.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Docker disk usage grows quietly because every part of it accumulates independently \u2014 images, stopped containers, volumes, build cache, and container logs, which are the one nobody expects and which no Docker command reports on. Cleaning it up is easy. Cleaning it up without destroying something takes about five more minutes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is the order I work through it: measure first, reclaim from safest to most destructive, then fix the thing that caused the growth so you are not back here next month.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Measure before you delete<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Every cleanup starts here, and skipping it is how people delete the wrong thing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker system df<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">That gives you four rows \u2014 Images, Containers, Local Volumes, Build Cache \u2014 with a total size and a reclaimable figure for each. The reclaimable column is the one that matters. If build cache is eleven gigabytes and all of it is reclaimable, you have found your win and you never need to go near volumes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For the itemised version:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker system df -v<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now you can see individual images with their sizes, which containers are using what, and which volumes have no container attached. Read this before running anything destructive.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Two more views worth having open:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># What is actually running, and what is just sitting there stopped\ndocker ps -a --format 'table {{.Names}}t{{.Image}}t{{.Status}}t{{.Size}}'\n\n# Images by age, oldest first\ndocker images --format 'table {{.Repository}}:{{.Tag}}t{{.Size}}t{{.CreatedSince}}'<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Reclaim in order, safest first<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">These are ordered deliberately. Work down the list and stop as soon as you have enough space. Most of the time you never reach step four.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. Stopped containers<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># See what would go\ndocker ps -a --filter status=exited --filter status=created\n\ndocker container prune<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This removes stopped containers and their writable layers. Anything running is untouched, and named volumes attached to those containers survive \u2014 only the container&#8217;s own layer goes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The one caveat: if a stopped container held state in its writable layer rather than in a volume, that state is gone. That is a design problem rather than a cleanup problem, but it is worth a glance before you confirm.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Build cache<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">On any machine that builds images regularly, this is usually the biggest single win and it is completely safe. Build cache is derived data. Deleting it costs you a slower next build and nothing else.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Everything older than a week\ndocker builder prune --filter \"until=168h\"\n\n# Everything, no exceptions\ndocker builder prune -a<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. Dangling images<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># Look first\ndocker images -f dangling=true\n\ndocker image prune<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Without <code>-a<\/code>, this removes only dangling images \u2014 untagged layers left behind when a rebuild moved a tag to a new image. They are almost always genuine garbage.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Unused images \u2014 read this one carefully<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>docker image prune -a<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Adding <code>-a<\/code> changes the meaning completely. It removes every image that does not have at least one container associated with it \u2014 running <em>or<\/em> stopped. So an image you pulled for a job that runs weekly, with no container currently existing, is gone. It will pull again, which is fine if you have bandwidth and the registry is reachable, and much less fine at 3am on a machine with a slow link.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Safer in most cases is an age filter, which keeps anything recent:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker image prune -a --filter \"until=336h\"   # older than 14 days<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">5. Volumes \u2014 the one that loses data<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Volumes are where databases live. Treat this step as a data operation, not a cleanup.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Before removing anything, look inside the candidates. This mounts each dangling volume read-only into a throwaway container so you can see what is actually in it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker volume ls -qf dangling=true | while read -r v; do\n  echo \"=== $v\"\n  docker run --rm -v \"$v\":\/vol:ro alpine sh -c 'du -sh \/vol; ls -la \/vol' 2&gt;\/dev\/null | head -12\ndone<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you see anything resembling a data directory, back it up before it goes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker run --rm \n  -v my-volume:\/vol:ro \n  -v \"$PWD\":\/backup \n  alpine tar czf \/backup\/my-volume.tar.gz -C \/vol .<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Only then:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker volume prune<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On recent Docker versions this prunes only anonymous volumes by default, with <code>--all<\/code> needed to include named ones \u2014 a genuinely good safety change. Older versions removed named volumes too. Check which behaviour you have before trusting it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker version --format '{{.Server.Version}}'\ndocker volume prune --help<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">The gigabytes Docker never tells you about<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Here is the part that catches experienced people. Container logs do not appear in <code>docker system df<\/code> at all, and no prune command touches them. A chatty application with the default logging driver will happily write tens of gigabytes and nothing in Docker&#8217;s own tooling will mention it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo du -sh \/var\/lib\/docker\/containers\/*\/*-json.log | sort -h | tail -10<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To map a log file back to the container that owns it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker ps -aq | xargs docker inspect --format '{{.Name}} {{.LogPath}}'<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Truncate, do not delete<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This matters. Deleting a log file that a running container still has open removes the directory entry but not the data \u2014 the kernel keeps the blocks allocated until the process closes the descriptor, so <code>df<\/code> shows no improvement and you are left confused. Truncate instead:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo truncate -s 0 \/var\/lib\/docker\/containers\/&lt;container-id&gt;\/&lt;container-id&gt;-json.log<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Then stop it happening again<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Set a global default in <code>\/etc\/docker\/daemon.json<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"log-driver\": \"json-file\",\n  \"log-opts\": {\n    \"max-size\": \"10m\",\n    \"max-file\": \"3\"\n  }\n}<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl restart docker<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">One thing people get wrong here: this applies to <strong>newly created containers only<\/strong>. Anything already running keeps the logging config it was created with. You have to recreate those containers for the limit to take effect \u2014 restarting them is not enough.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">While you are in that file, cap the build cache too:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"log-driver\": \"json-file\",\n  \"log-opts\": {\n    \"max-size\": \"10m\",\n    \"max-file\": \"3\"\n  },\n  \"builder\": {\n    \"gc\": {\n      \"enabled\": true,\n      \"defaultKeepStorage\": \"20GB\"\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Automating it without automating a disaster<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A weekly cron is worth having, provided it only ever does the safe operations. The rule is simple: never put <code>--volumes<\/code> in anything unattended.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \/etc\/cron.d\/docker-prune\n# Weekly, Sunday 03:00. Containers, networks, dangling images and build\n# cache older than seven days. No volumes, ever.\n0 3 * * 0 root \/usr\/bin\/docker system prune -f --filter \"until=168h\" &gt;&gt; \/var\/log\/docker-prune.log 2&gt;&amp;1<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note what <code>docker system prune<\/code> covers without flags: stopped containers, unused networks, dangling images and build cache. It does <em>not<\/em> touch volumes unless you explicitly pass <code>--volumes<\/code>, and it does not remove tagged images unless you pass <code>-a<\/code>. Those two flags are the whole difference between a routine job and an incident.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">If you are tempted to add <code>--volumes<\/code> to a cron job so you do not have to think about it again, you have swapped a disk space problem for a data loss problem on a timer.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Pruned everything, df has not moved<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Deleted files still held open by a running process. Find them:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo lsof +L1 | head -20<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Restarting the process that holds the descriptor releases the blocks. If it is the Docker daemon itself, a <code>systemctl restart docker<\/code> does it, at the cost of bouncing every container without a restart policy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">&#8220;No space left on device&#8221; but df shows free space<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You are out of inodes rather than bytes. Docker&#8217;s layered storage creates enormous numbers of small files:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>df -i<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The fix is the same \u2014 prune images and build cache, which is where the file count lives.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">overlay2 is huge and I have hardly any images<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo du -sh \/var\/lib\/docker\/*\nsudo du -sh \/var\/lib\/docker\/overlay2 2&gt;\/dev\/null<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Usually build cache or container writable layers rather than images. Do not delete anything under <code>overlay2<\/code> by hand \u2014 the directory names are referenced in Docker&#8217;s metadata, and removing them directly corrupts the daemon&#8217;s view of the world. Always go through <code>docker<\/code> commands.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Running low and need space right now<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Fastest safe sequence, in order:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker builder prune -a -f\ndocker container prune -f\ndocker image prune -f\nsudo truncate -s 0 \/var\/lib\/docker\/containers\/*\/*-json.log<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Four commands, no volumes touched, no tagged images removed. That resolves the large majority of Docker disk usage emergencies.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Common mistakes<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Reaching for <code>docker system prune -a --volumes<\/code> first because it is the top search result.<\/li>\n\n<li>Putting <code>--volumes<\/code> in a cron job.<\/li>\n\n<li>Deleting log files instead of truncating them, then wondering why <code>df<\/code> did not change.<\/li>\n\n<li>Setting log limits in <code>daemon.json<\/code> and assuming existing containers pick them up. They do not.<\/li>\n\n<li>Removing directories under <code>\/var\/lib\/docker\/overlay2<\/code> by hand.<\/li>\n\n<li>Storing application data in a container&#8217;s writable layer rather than a volume, so cleanup destroys it.<\/li>\n\n<li>Never running <code>docker system df<\/code>, and so deleting the wrong category entirely.<\/li>\n\n<li>Assuming inodes cannot be the problem.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Best practices<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set log rotation in <code>daemon.json<\/code> on every host, on day one.<\/li>\n\n<li>Cap build cache with the builder GC settings rather than relying on manual pruning.<\/li>\n\n<li>Use named volumes for anything you care about, so cleanup and data are clearly separated.<\/li>\n\n<li>Use multi-stage builds and a real <code>.dockerignore<\/code>. Smaller images mean less to clean up.<\/li>\n\n<li>Automate only the safe operations, with an age filter, and log what the job removed.<\/li>\n\n<li>Alert on disk usage at 80% so cleanup is a scheduled task rather than an incident.<\/li>\n\n<li>On busy build hosts, give <code>\/var\/lib\/docker<\/code> its own partition so a runaway cache cannot take the OS down with it.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Frequently asked questions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Is <code>docker system prune<\/code> safe to run?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Without flags, yes, on most systems. It removes stopped containers, unused networks, dangling images and build cache. Adding <code>-a<\/code> also removes tagged images with no container attached. Adding <code>--volumes<\/code> is the one that can lose data.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Will pruning delete my database?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Only if the database lives in a volume and you pass <code>--volumes<\/code>, or it lives in a container&#8217;s writable layer and you prune that container. If it is in a named volume attached to a running container, ordinary pruning will not touch it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Why does <code>docker system df<\/code> not match <code>du<\/code>?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Two reasons. It does not count container logs at all, and it accounts for shared image layers once rather than per image. <code>du -sh \/var\/lib\/docker<\/code> is the honest total.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How do I stop logs growing without limit?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Set <code>max-size<\/code> and <code>max-file<\/code> under <code>log-opts<\/code> in <code>\/etc\/docker\/daemon.json<\/code>, restart the daemon, then recreate existing containers so they pick up the new configuration.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Can I move Docker&#8217;s storage to another disk?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes, with <code>data-root<\/code> in <code>daemon.json<\/code>. Stop Docker, copy <code>\/var\/lib\/docker<\/code> across preserving ownership and extended attributes, point <code>data-root<\/code> at the new location, then start it again. Copy rather than move until you have confirmed it works.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Does pruning affect running containers?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. Prune operations skip anything in use. The risk is always to things that are stopped, dangling or unattached \u2014 which is exactly why checking what is stopped before you prune is worth the thirty seconds.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping up<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Docker disk usage is four categories that grow independently, plus a fifth \u2014 logs \u2014 that hides from Docker&#8217;s own accounting. Run <code>docker system df<\/code>, work down from build cache to volumes, and stop as soon as you have the space. The nuclear option exists, but reaching for it first is how people discover which of their volumes mattered.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Once the immediate problem is solved, spend ten minutes on log rotation and builder GC. Those two settings turn this from a recurring emergency into something you never think about again.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Need a hand with Docker in production?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I work with teams on container infrastructure \u2014 image sizes that got out of hand, build pipelines that cache badly, storage and logging defaults that were never set, and monitoring that catches a full disk before the alert does.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you would rather not spend the evening on it, you can hire me on Upwork.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/www.upwork.com\/freelancers\/~01f15a912ad84a6620\" target=\"_blank\" rel=\"noreferrer noopener\">Work with me on Upwork<\/a><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>The top search result tells you to run docker system prune -a &#8211;volumes. It frees the space and deletes your database. Here is how to measure Docker disk usage properly, reclaim it from safest to most destructive, and fix the logs that Docker never reports on.<\/p>\n","protected":false},"author":1,"featured_media":47,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[24,26,63],"tags":[94,9,3,105,8,7,21,6,22,106,72,4],"class_list":["post-46","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","category-linux","category-system-administration","tag-automation","tag-containers","tag-devops","tag-disk-space","tag-docker","tag-docker-compose","tag-infrastructure","tag-linux","tag-self-hosting","tag-storage","tag-sysadmin","tag-troubleshooting","entry","has-media"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Cleaning Up Docker Disk Usage Safely<\/title>\n<meta name=\"description\" content=\"Reclaim Docker disk usage without losing data: measure with system df, prune safest first, and fix the container logs Docker never reports on.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Cleaning Up Docker Disk Usage Safely\" \/>\n<meta property=\"og:description\" content=\"Reclaim Docker disk usage without losing data: measure with system df, prune safest first, and fix the container logs Docker never reports on.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/\" \/>\n<meta property=\"og:site_name\" content=\"John Nessime\" \/>\n<meta property=\"article:published_time\" content=\"2026-07-31T19:52:19+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-07-31T19:52:21+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/07\/docker-disk-usage-cleanup-featured.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"800\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"John Nessime\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"John Nessime\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/docker-disk-usage-cleanup\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/docker-disk-usage-cleanup\\\/\"},\"author\":{\"name\":\"John Nessime\",\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/#\\\/schema\\\/person\\\/ede0b56d0c808f123f57d5d796902105\"},\"headline\":\"Cleaning Up Docker Disk Usage Safely\",\"datePublished\":\"2026-07-31T19:52:19+00:00\",\"dateModified\":\"2026-07-31T19:52:21+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/docker-disk-usage-cleanup\\\/\"},\"wordCount\":1618,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/#\\\/schema\\\/person\\\/ede0b56d0c808f123f57d5d796902105\"},\"image\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/docker-disk-usage-cleanup\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/docker-disk-usage-cleanup-featured.png\",\"keywords\":[\"Automation\",\"Containers\",\"DevOps\",\"Disk Space\",\"Docker\",\"Docker Compose\",\"Infrastructure\",\"Linux\",\"Self Hosting\",\"Storage\",\"Sysadmin\",\"Troubleshooting\"],\"articleSection\":[\"DevOps\",\"Linux\",\"System Administration\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/docker-disk-usage-cleanup\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/docker-disk-usage-cleanup\\\/\",\"url\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/docker-disk-usage-cleanup\\\/\",\"name\":\"Cleaning Up Docker Disk Usage Safely\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/docker-disk-usage-cleanup\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/docker-disk-usage-cleanup\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/docker-disk-usage-cleanup-featured.png\",\"datePublished\":\"2026-07-31T19:52:19+00:00\",\"dateModified\":\"2026-07-31T19:52:21+00:00\",\"description\":\"Reclaim Docker disk usage without losing data: measure with system df, prune safest first, and fix the container logs Docker never reports on.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/docker-disk-usage-cleanup\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/docker-disk-usage-cleanup\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/docker-disk-usage-cleanup\\\/#primaryimage\",\"url\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/docker-disk-usage-cleanup-featured.png\",\"contentUrl\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/docker-disk-usage-cleanup-featured.png\",\"width\":1200,\"height\":800,\"caption\":\"Docker disk usage breakdown showing images, containers, volumes, build cache and hidden container logs with reclaimable amounts, beside a risk ladder ranking prune commands from safe to destructive\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/docker-disk-usage-cleanup\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Cleaning Up Docker Disk Usage Safely\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/\",\"name\":\"John Nessime\",\"description\":\"Cloud, DevOps, Data &amp; AI \u2014 Built, Tested, Explained\",\"publisher\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/#\\\/schema\\\/person\\\/ede0b56d0c808f123f57d5d796902105\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/#\\\/schema\\\/person\\\/ede0b56d0c808f123f57d5d796902105\",\"name\":\"John Nessime\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/cropped-jn.png\",\"url\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/cropped-jn.png\",\"contentUrl\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/cropped-jn.png\",\"width\":512,\"height\":512,\"caption\":\"John Nessime\"},\"logo\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/cropped-jn.png\"},\"description\":\"AWS Certified Solutions Architect helping businesses build reliable cloud, data, reporting, and automation solutions. I help startups, agencies, and growing businesses replace manual processes and disconnected data with practical AWS architectures, clean data pipelines, useful dashboards, and maintainable automation.\",\"sameAs\":[\"https:\\\/\\\/john-nessime.com\\\/blog\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/john-m-nessime\"],\"url\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/author\\\/johnnessime\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Cleaning Up Docker Disk Usage Safely","description":"Reclaim Docker disk usage without losing data: measure with system df, prune safest first, and fix the container logs Docker never reports on.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/","og_locale":"en_US","og_type":"article","og_title":"Cleaning Up Docker Disk Usage Safely","og_description":"Reclaim Docker disk usage without losing data: measure with system df, prune safest first, and fix the container logs Docker never reports on.","og_url":"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/","og_site_name":"John Nessime","article_published_time":"2026-07-31T19:52:19+00:00","article_modified_time":"2026-07-31T19:52:21+00:00","og_image":[{"width":1200,"height":800,"url":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/07\/docker-disk-usage-cleanup-featured.png","type":"image\/png"}],"author":"John Nessime","twitter_card":"summary_large_image","twitter_misc":{"Written by":"John Nessime","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/#article","isPartOf":{"@id":"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/"},"author":{"name":"John Nessime","@id":"https:\/\/john-nessime.com\/blog\/#\/schema\/person\/ede0b56d0c808f123f57d5d796902105"},"headline":"Cleaning Up Docker Disk Usage Safely","datePublished":"2026-07-31T19:52:19+00:00","dateModified":"2026-07-31T19:52:21+00:00","mainEntityOfPage":{"@id":"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/"},"wordCount":1618,"commentCount":0,"publisher":{"@id":"https:\/\/john-nessime.com\/blog\/#\/schema\/person\/ede0b56d0c808f123f57d5d796902105"},"image":{"@id":"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/#primaryimage"},"thumbnailUrl":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/07\/docker-disk-usage-cleanup-featured.png","keywords":["Automation","Containers","DevOps","Disk Space","Docker","Docker Compose","Infrastructure","Linux","Self Hosting","Storage","Sysadmin","Troubleshooting"],"articleSection":["DevOps","Linux","System Administration"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/","url":"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/","name":"Cleaning Up Docker Disk Usage Safely","isPartOf":{"@id":"https:\/\/john-nessime.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/#primaryimage"},"image":{"@id":"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/#primaryimage"},"thumbnailUrl":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/07\/docker-disk-usage-cleanup-featured.png","datePublished":"2026-07-31T19:52:19+00:00","dateModified":"2026-07-31T19:52:21+00:00","description":"Reclaim Docker disk usage without losing data: measure with system df, prune safest first, and fix the container logs Docker never reports on.","breadcrumb":{"@id":"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/#primaryimage","url":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/07\/docker-disk-usage-cleanup-featured.png","contentUrl":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/07\/docker-disk-usage-cleanup-featured.png","width":1200,"height":800,"caption":"Docker disk usage breakdown showing images, containers, volumes, build cache and hidden container logs with reclaimable amounts, beside a risk ladder ranking prune commands from safe to destructive"},{"@type":"BreadcrumbList","@id":"https:\/\/john-nessime.com\/blog\/devops\/docker-disk-usage-cleanup\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/john-nessime.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Cleaning Up Docker Disk Usage Safely"}]},{"@type":"WebSite","@id":"https:\/\/john-nessime.com\/blog\/#website","url":"https:\/\/john-nessime.com\/blog\/","name":"John Nessime","description":"Cloud, DevOps, Data &amp; AI \u2014 Built, Tested, Explained","publisher":{"@id":"https:\/\/john-nessime.com\/blog\/#\/schema\/person\/ede0b56d0c808f123f57d5d796902105"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/john-nessime.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/john-nessime.com\/blog\/#\/schema\/person\/ede0b56d0c808f123f57d5d796902105","name":"John Nessime","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/07\/cropped-jn.png","url":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/07\/cropped-jn.png","contentUrl":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/07\/cropped-jn.png","width":512,"height":512,"caption":"John Nessime"},"logo":{"@id":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/07\/cropped-jn.png"},"description":"AWS Certified Solutions Architect helping businesses build reliable cloud, data, reporting, and automation solutions. I help startups, agencies, and growing businesses replace manual processes and disconnected data with practical AWS architectures, clean data pipelines, useful dashboards, and maintainable automation.","sameAs":["https:\/\/john-nessime.com\/blog","https:\/\/www.linkedin.com\/in\/john-m-nessime"],"url":"https:\/\/john-nessime.com\/blog\/author\/johnnessime\/"}]}},"_links":{"self":[{"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/posts\/46","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/comments?post=46"}],"version-history":[{"count":1,"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/posts\/46\/revisions"}],"predecessor-version":[{"id":48,"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/posts\/46\/revisions\/48"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/media\/47"}],"wp:attachment":[{"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/media?parent=46"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/categories?post=46"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/tags?post=46"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}