Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 

Repository files navigation

docker-compose-auto-update

A single-file cron script that keeps all your Docker Compose projects up to date. It walks a directory tree, finds every docker-compose.yml / docker-compose.yaml, pulls the latest images, and recreates only the services whose image actually changed — with minimal downtime and without touching anything you stopped on purpose.

Built for small self-hosted setups (home servers, Raspberry Pi, a single VPS) where tools like Watchtower feel like overkill.

How it works

For each discovered Compose project the script:

  1. Skips it if it has no external images (build-only project).
  2. Skips it if it is not currently running — intentionally stopped projects are never woken up.
  3. Runs docker compose pull --ignore-buildable.
  4. Compares the image ID each running container uses against the image ID its tag now points to. This catches updates reliably, including the case where two projects share the same image and the first one already pulled the new version.
  5. If anything changed, runs docker compose up -d, which recreates only the outdated services (no full down, networks stay intact).

Afterwards it removes dangling images only — images belonging to stopped or manually managed projects are left alone.

Robustness

  • A failure in one project (registry outage, rate limit, broken compose file) is logged and never aborts the run for the remaining projects.
  • An flock-based lock prevents overlapping runs if cron fires while a previous run is still in progress.
  • Paths with spaces are handled correctly (find -print0).
  • set -euo pipefail guards against silent breakage everywhere else.

Requirements

  • Bash, GNU coreutils, flock (present on any normal Linux)
  • Docker with the Compose v2 plugin (docker compose), v2.20+ for --ignore-buildable
    • On older Compose, replace the flag with --ignore-pull-failures or remove it (projects mixing build: + image: will then be skipped on pull errors, but the run continues).

Installation

git clone https://github.com/WhyElEss/docker-compose-auto-update.git
cd docker-compose-auto-update
chmod +x update-all-docker.sh

Run it once manually to verify:

BASE_DIR=/home/you ./update-all-docker.sh
tail -50 ~/cron-tasks/update-all-docker.log

Then schedule it, e.g. daily at 05:00:

0 5 * * * BASE_DIR=/home/you /home/you/docker-compose-auto-update/update-all-docker.sh

Configuration

Everything is overridable via environment variables:

Variable Default Purpose
BASE_DIR $HOME Root of the tree searched for projects (max depth 5)
LOGDIR $HOME/cron-tasks Directory for the log and lock files
LOGFILE $LOGDIR/update-all-docker.log Log file (append-only)
LOCKFILE $LOGDIR/update-all-docker.lock Lock file for flock
DOCKER_BIN /usr/bin/docker Docker binary (absolute path is cron-safe)

Example log output

=== 2026-07-20 05:00:01 : start ===
--- Checking directory: /home/you/homebridge
Pulling latest images...
Image updated: homebridge/homebridge:latest
Updates detected. Recreating services in /home/you/homebridge...
Recreate complete.
--- Checking directory: /home/you/uptime-kuma
Pulling latest images...
No updates found.
Removing dangling images...
Image cleanup complete.
=== 2026-07-20 05:03:12 : end ===

Caveats

  • Services pinned to a fixed digest (image: foo@sha256:...) will never update — which is exactly what pinning is for.
  • The script updates whatever the tag moves to; if you track :latest, you accept upstream's release cadence. Pin major-version tags (e.g. postgres:16) for more predictable behavior.
  • Compose projects deeper than 5 directory levels below BASE_DIR are not discovered (tune -maxdepth in the script if needed).

License

MIT

About

Cron script that auto-updates all Docker Compose projects on a host, recreating only the services whose image actually changed. A lightweight Watchtower alternative.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages