Scheduled Bash helpers that remove old, unused Docker build cache before it fills Docker's storage.
Docker build cache can accumulate on any host that performs image builds, including self-hosted Gitea and Forgejo Actions runners. On Unraid it commonly consumes space inside docker.img; on a typical Linux host it consumes space on the filesystem containing Docker's data root.
| Script | Intended system | Storage reporting |
|---|---|---|
unraid_docker_build_prune.sh |
Unraid with its standard Docker layout | Checks /var/lib/docker, which is commonly backed by docker.img |
linux_docker_build_prune.sh |
Linux Docker hosts, including rootful and rootless installations | Discovers Docker's data root and reports its filesystem when the daemon is local |
Both scripts:
- Show Docker storage usage before cleanup.
- Remove unused build cache older than 7 days by default.
- Show usage again after cleanup.
- Write complete output to a timestamped log.
- Return a nonzero exit status when a required command fails.
Caution
Both scripts run docker builder prune --all --force with an age filter. Docker defines --all here as all unused build cache, not all Docker objects. Containers, images, networks, and volumes are not pruned. Deleted cache must be rebuilt during a future Docker build, which can make that build slower.
Use the Unraid script when installing through the Unraid User Scripts plugin. It intentionally retains the known-working Unraid paths:
/usr/bin/docker
/var/lib/docker
Use the Linux script on Ubuntu, Debian, Fedora, Rocky Linux, or another Linux distribution. It discovers:
- The Docker CLI from
PATHorDOCKER_BIN. - Docker's data root and storage driver from
docker info. - The selected Docker context and endpoint.
The Linux version is not intended for macOS, Windows, or Docker Desktop. It can prune a remote Docker daemon selected by a Docker context, but it skips the host filesystem report because the remote path is not locally accessible.
- Unraid with Docker enabled.
- Bash and
/usr/bin/docker, which are standard on Unraid. - The User Scripts plugin.
- Root privileges. User Scripts runs scripts as root.
- Install User Scripts from the Unraid Apps tab if it is not already installed.
- Open Settings > User Scripts.
- Select Add New Script and name it
docker_build_prune. - Open its settings, select Edit Script, and replace the contents with
unraid_docker_build_prune.sh. - Save the script.
- Run it manually once and review its output and log.
- Open the schedule dropdown and select Weekly. The entry will then show Scheduled Weekly.
The built-in weekly schedule is a reasonable starting point and requires no custom cron expression.
The User Scripts editor does not provide fields for these environment variables. To change the defaults, add the desired exports immediately after set -Eeuo pipefail:
export CACHE_MAX_AGE=336h
export LOG_DIR=/mnt/user/appdata/docker-build-prune/logsThat example retains 14 days of cache and stores persistent logs in the appdata share.
- Linux with Bash.
- A working Docker CLI and reachable Docker Engine.
- Permission to use the selected Docker daemon.
- Standard Linux utilities including
df,tee,date, andhostname.
The script does not require root when the current user already has permission to access Docker. Rootless Docker should be cleaned by the user who owns that Docker daemon.
Download the Linux script without executing it automatically:
curl --fail --silent --show-error \
--output /tmp/linux_docker_build_prune.sh \
https://raw.githubusercontent.com/Grasfer/unraid_docker_build_prune/main/linux_docker_build_prune.sh
less /tmp/linux_docker_build_prune.sh
bash -n /tmp/linux_docker_build_prune.shInstall it system-wide after reviewing it:
sudo install -m 0755 \
/tmp/linux_docker_build_prune.sh \
/usr/local/sbin/docker-build-pruneRun it manually once:
sudo /usr/local/sbin/docker-build-pruneDo not use sudo for a rootless Docker daemon. Run it as the owning user instead.
Example unit files are included in systemd/:
sudo install -m 0644 \
systemd/docker-build-prune.service \
systemd/docker-build-prune.timer \
/etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now docker-build-prune.timer
systemctl list-timers docker-build-prune.timerThe included timer runs weekly, persists across downtime, and adds a randomized delay of up to 15 minutes.
The system service targets the root-owned Docker daemon. For rootless Docker, create equivalent user units under ~/.config/systemd/user/ and manage them with systemctl --user.
As an alternative, open root's crontab:
sudo crontab -eExample weekly entry for Sunday at 04:00:
0 4 * * 0 /usr/local/sbin/docker-build-pruneUse the owning user's crontab instead of root's for a rootless Docker daemon.
| Variable | Script | Default | Purpose |
|---|---|---|---|
CACHE_MAX_AGE |
Both | 168h |
Remove unused cache older than this duration. |
LOG_DIR |
Both | /tmp |
Directory for timestamped logs. |
DOCKER_BIN |
Linux | docker from PATH |
Docker executable name or absolute path. |
DOCKER_HOST |
Linux/Docker CLI | Current context | Optionally select a Docker endpoint using Docker's standard environment variable. |
Docker duration values use units such as h, m, and s. Examples:
72h = 3 days
168h = 7 days
336h = 14 days
Run the Linux version with custom settings:
CACHE_MAX_AGE=336h \
LOG_DIR=/var/log/docker-build-prune \
DOCKER_BIN=/usr/bin/docker \
sudo --preserve-env=CACHE_MAX_AGE,LOG_DIR,DOCKER_BIN \
/usr/local/sbin/docker-build-pruneFor scheduled Linux use, edit the Environment= values in the provided systemd service.
The default log name is:
/tmp/docker-build-prune-2026-07-17_14-30-00.log
/tmp is temporary and logs there may disappear at reboot. Choose a persistent LOG_DIR if logs must survive reboot:
- Unraid example:
/mnt/user/appdata/docker-build-prune/logs - Linux example:
/var/log/docker-build-prune
Persistent logs are not automatically rotated. One weekly text log is normally small, but administrators should add a retention policy if they keep logs indefinitely.
The cleanup command is:
docker builder prune \
--all \
--force \
--filter "until=168h"It removes build-cache records that are both:
- Unused by an active build.
- Older than the configured age.
It does not run any of these broader commands:
docker system prune
docker image prune
docker container prune
docker volume prune
Do not manually delete Docker-managed files from /var/lib/docker or another Docker data root.
Docker object usage:
docker system dfDocker's configured data root and storage driver:
docker info --format 'Root={{.DockerRootDir}} Driver={{.Driver}}'Filesystem usage for a local daemon:
docker_root="$(docker info --format '{{.DockerRootDir}}')"
df -h -- "$docker_root"On Unraid, confirm whether the Docker data root is backed by docker.img:
findmnt -T /var/lib/docker
losetup -l | grep docker.imgdocker system df reports unused cache that is potentially reclaimable. The script only removes unused records older than CACHE_MAX_AGE. Newer records remain available to speed up future builds.
Cache newer than the retention period remains. Cache actively used by a build cannot be removed.
No. The scripts only invoke docker builder prune; they do not use the broader prune commands listed above.
Not necessarily. docker builder prune cleans the cache associated with the selected Docker builder on the selected daemon. Named Buildx builders, remote builders, and Docker-in-Docker runners can maintain separate cache stores.
List available builders with:
docker buildx lsThose builders may need an explicit, builder-specific cleanup policy. The scripts deliberately do not discover and prune every builder automatically because that would broaden their deletion scope.
Docker must rebuild deleted layers the next time they are needed. Increase CACHE_MAX_AGE if keeping more cache is worth the additional disk usage.
- Docker was not found: install the Docker CLI, fix
PATH, or setDOCKER_BINwhen using the Linux script. - Permission denied connecting to Docker: run the script as an authorized user. Use root for the system Docker daemon, or the owning user for rootless Docker.
- Docker daemon is unreachable: verify
docker infosucceeds with the same user and environment used by the schedule. - No log after reboot:
/tmpis temporary; configure a persistentLOG_DIR. - Cache grows quickly: shorten
CACHE_MAX_AGE, schedule cleanup more often, and check for additional Buildx or Docker-in-Docker caches. - Filesystem usage is skipped: the Linux script detected a remote or unknown Docker endpoint.
docker system dfstill reports Docker object usage from the selected daemon.
These are community scripts and are not affiliated with or supported by Unraid or Docker. Review the source, run it manually, and verify the result before scheduling it. Build cache is disposable acceleration data, not a backup.
Licensed under the MIT License.