Turbootzz/freshdock

Keep your docker containers up to date

Rust

55

59 commits

updated Sep 7, 2026

See the code
container-image-cleanup
container-management
docker
docker-image-updater
scheduler-service
updater

See what people are saying (1)

SourceMessageScoreDate

Watchtower is archived, so I built freshdock: a Docker auto-updater that rolls back when the new image fails its healthcheck (r/selfhosted)

I ran Watchtower for years and mostly forgot it existed. Then it got archived in December, and its embedded SDK speaks Docker API 1.25 while Engine 29 raised the floor to 1.44, so on a current daemon it just stops talking. The forks keep it alive, and if that's all you need, use one. What bugged me…

0

Sep 17, 2026

README

freshdock logo

freshdock

A modern, health-gated Docker container auto-updater. A maintained successor to Watchtower, in a single Rust binary.

CI Crate docs GHCR image License: Apache-2.0 Sponsor

Website · Quickstart · Docs · Configuration · From Watchtower


Why freshdock instead of Watchtower? See the side-by-side comparison.

What it does

freshdock watches your running containers, notices when a newer image is published, and updates them safely: a broken new image rolls back automatically instead of leaving you with a dead service.

CapabilityWhat you get
Health-gated rollbackA container counts as updated only after its healthcheck passes, or after a grace period if it has none. If the new image fails to come up, the previous container is restored and you are notified.
Per-container modesDrive each container with Docker labels: live, nightly, weekly, monthly, watch, off. Mix them freely on one daemon.
Five registriesDocker Hub, GHCR, Quay.io, lscr.io, and any OCI bearer-token registry, anonymous or authenticated.
Four notifiersWebhook, Discord, Telegram, and SMTP, each subscribable to the events it cares about.
Lifecycle hooksRun commands inside the container around an update. A pre-update hook can veto or defer (exit 75); a post-update hook handles maintenance like cache clears.
Compose-aware rolloutsA Compose project updates as one unit: the one-shot migrate service your app waits on is re-run before the new code starts, and a failed migration aborts the rollout. Read from Compose's own labels, no compose file needed.
VPN stacks survive updatesContainers routed through another container's network (network_mode: container:X, the gluetun pattern) are re-attached after that container updates instead of being left offline.
Watchtower drop-inReads com.centurylinklabs.watchtower.* labels (enable, monitor-only, lifecycle hooks) directly, so a fleet migrates without relabelling. FRESHDOCK_WATCH_ALL=true restores Watchtower's opt-out model, still on watch until FRESHDOCK_DEFAULT_MODE picks an updating mode.
Optional cleanupRemove superseded images after a healthy update; optionally prune dangling images.
Single static binaryUnder 10 MB, no runtime dependencies. No JVM, no Go runtime, no 100 MB image to manage your homelab.

freshdock is opt-in: it ignores every container until you set freshdock.enable=true, and an enabled container with no explicit mode defaults to watch (detect and notify, never restart). One narrow exception: inside a Compose project, an unlabelled one-shot that another service waits on is re-run as part of the rollout. An explicit opt-out still wins. See Compose projects. To include every container unless it opts out, see watching every container.

Quickstart

Label a container to opt it in, then watch it with a read-only socket:

# docker-compose.yml
services:
  web:
    image: nginx:1.27
    labels:
      - "freshdock.enable=true"      # opt in; mode defaults to watch

  freshdock:
    image: ghcr.io/turbootzz/freshdock:latest
    command: ["run"]
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    restart: unless-stopped
freshdock check    # read-only: which containers have updates available?

To let it update something, switch to freshdock.mode=nightly and give the daemon a writable socket. Full walkthrough in the Quickstart.

Install

# crates.io
cargo install freshdock

# container image (multi-arch: amd64, arm64, armv7)
docker run -d --name freshdock --restart unless-stopped \
  -v /var/run/docker.sock:/var/run/docker.sock \
  ghcr.io/turbootzz/freshdock:latest run

Prebuilt static-musl binaries (amd64, arm64, armv7) are attached to each release, with a SHA256SUMS file to verify them (sha256sum -c SHA256SUMS). From source: clone the repo and run just build (binary at target/release/freshdock).

Update modes

ModeBehaviour
livePoll frequently; pull and recreate on every new digest.
nightly / weekly / monthlyCheck on a cron schedule (default 04:00); recreate if newer.
watchDetect updates and notify only, never pull or restart.
offNever updated. Still listed by freshdock check.

Set the mode (and an optional cron override) with labels:

    labels:
      - "freshdock.enable=true"
      - "freshdock.mode=weekly"
      - "freshdock.schedule=0 2 * * 1"   # 02:00 every Monday (overrides the default)

Full label vocabulary and cron syntax: Configuration and Scheduling.

Documentation

QuickstartUp and running in a minute.
ConfigurationEvery label, env var, and freshdock.toml table (the single source of truth).
CLI referencecheck, recreate, run, and all flags.
Scheduling & modesUpdate modes and cron syntax.
Compose projectsA stack updated as one unit: one-shot migrations, depends_on ordering.
NotificationsWebhook, Discord, Telegram, SMTP.
Health & rollbackThe recreate lifecycle and image cleanup.
Lifecycle hooksPre-update and post-update commands.
Registry authPrivate registries and credentials.
DeploymentContainer, systemd, socket permissions, compatibility.
TroubleshootingSymptom-first fixes for common first-run issues.
Migrating from WatchtowerLabel/flag translation.
Architecture & roadmapDesign, phases, goals, risks.

Runnable example stacks: examples/compose/. A commented config template: freshdock.toml.example.

Why freshdock

Watchtower was the de-facto Docker auto-updater for years. Its maintainers archived it on 17 December 2025, and it shipped an embedded Docker SDK (API 1.25) incompatible with Docker Engine 29+. The community has forks, but none combine what matters for a small homelab:

  1. Modern Docker API: the API version is negotiated with your daemon at connect time via bollard, so freshdock speaks the newest API that daemon supports.
  2. Safe updates: a broken new image rolls back automatically instead of leaving a dead container.
  3. Small footprint: a single static binary, not a 100+ MB image to manage your other containers.

Compatibility

PlatformStatus
Plain DockerPrimary target. The API version is negotiated per daemon; CI exercises the Docker engine shipped on GitHub's ubuntu-latest runners.
Docker Desktop (Linux, macOS, Windows)Supported.
Portainer (CE and Business)Supported via the same Docker socket.
Podman 4+Supported via the Docker-compatible socket.
Docker ComposeA project is updated as one unit: one-shot service_completed_successfully services are re-run first, the rest follow in depends_on order. Compose files are never read or written.
Compose-based UIs (Dockge, Komodo, and similar)Supported; the compose files themselves are untouched.
Kubernetes / SwarmOut of scope. Use platform-native mechanisms.

Socket discovery order, Podman paths, and the Docker API 1.44 floor for containers on more than one network are covered in Deployment.

Status & roadmap

Phases 0-7 are complete and freshdock has been stable since 1.0.0. The full plan and architecture live in the roadmap; release mechanics in RELEASE.md; per-version notes in CHANGELOG.md.

Contributing

Contributions are welcome. See CONTRIBUTING.md for local setup, the quality gates, and dependency hygiene. Security reports: SECURITY.md.

Support

freshdock is free and open source. If it keeps your homelab up to date, you can support its development through GitHub Sponsors. Sponsoring is optional; stars, bug reports, and pull requests help just as much.

License

freshdock is licensed under the Apache License 2.0.

Acknowledgements

  • Watchtower for being the standard for ten years and shaping the design space.
  • bollard for the Rust Docker SDK that makes any of this possible.

Contributors

Turbootzz/freshdock

Keep your docker containers up to date

Rust

55

59 commits

updated Sep 7, 2026

See the code
container-image-cleanup
container-management
docker
docker-image-updater
scheduler-service
updater

See what people are saying (1)

SourceMessageScoreDate

Watchtower is archived, so I built freshdock: a Docker auto-updater that rolls back when the new image fails its healthcheck (r/selfhosted)

I ran Watchtower for years and mostly forgot it existed. Then it got archived in December, and its embedded SDK speaks Docker API 1.25 while Engine 29 raised the floor to 1.44, so on a current daemon it just stops talking. The forks keep it alive, and if that's all you need, use one. What bugged me…

0

Sep 17, 2026

README

freshdock logo

freshdock

A modern, health-gated Docker container auto-updater. A maintained successor to Watchtower, in a single Rust binary.

CI Crate docs GHCR image License: Apache-2.0 Sponsor

Website · Quickstart · Docs · Configuration · From Watchtower


Why freshdock instead of Watchtower? See the side-by-side comparison.

What it does

freshdock watches your running containers, notices when a newer image is published, and updates them safely: a broken new image rolls back automatically instead of leaving you with a dead service.

CapabilityWhat you get
Health-gated rollbackA container counts as updated only after its healthcheck passes, or after a grace period if it has none. If the new image fails to come up, the previous container is restored and you are notified.
Per-container modesDrive each container with Docker labels: live, nightly, weekly, monthly, watch, off. Mix them freely on one daemon.
Five registriesDocker Hub, GHCR, Quay.io, lscr.io, and any OCI bearer-token registry, anonymous or authenticated.
Four notifiersWebhook, Discord, Telegram, and SMTP, each subscribable to the events it cares about.
Lifecycle hooksRun commands inside the container around an update. A pre-update hook can veto or defer (exit 75); a post-update hook handles maintenance like cache clears.
Compose-aware rolloutsA Compose project updates as one unit: the one-shot migrate service your app waits on is re-run before the new code starts, and a failed migration aborts the rollout. Read from Compose's own labels, no compose file needed.
VPN stacks survive updatesContainers routed through another container's network (network_mode: container:X, the gluetun pattern) are re-attached after that container updates instead of being left offline.
Watchtower drop-inReads com.centurylinklabs.watchtower.* labels (enable, monitor-only, lifecycle hooks) directly, so a fleet migrates without relabelling. FRESHDOCK_WATCH_ALL=true restores Watchtower's opt-out model, still on watch until FRESHDOCK_DEFAULT_MODE picks an updating mode.
Optional cleanupRemove superseded images after a healthy update; optionally prune dangling images.
Single static binaryUnder 10 MB, no runtime dependencies. No JVM, no Go runtime, no 100 MB image to manage your homelab.

freshdock is opt-in: it ignores every container until you set freshdock.enable=true, and an enabled container with no explicit mode defaults to watch (detect and notify, never restart). One narrow exception: inside a Compose project, an unlabelled one-shot that another service waits on is re-run as part of the rollout. An explicit opt-out still wins. See Compose projects. To include every container unless it opts out, see watching every container.

Quickstart

Label a container to opt it in, then watch it with a read-only socket:

# docker-compose.yml
services:
  web:
    image: nginx:1.27
    labels:
      - "freshdock.enable=true"      # opt in; mode defaults to watch

  freshdock:
    image: ghcr.io/turbootzz/freshdock:latest
    command: ["run"]
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    restart: unless-stopped
freshdock check    # read-only: which containers have updates available?

To let it update something, switch to freshdock.mode=nightly and give the daemon a writable socket. Full walkthrough in the Quickstart.

Install

# crates.io
cargo install freshdock

# container image (multi-arch: amd64, arm64, armv7)
docker run -d --name freshdock --restart unless-stopped \
  -v /var/run/docker.sock:/var/run/docker.sock \
  ghcr.io/turbootzz/freshdock:latest run

Prebuilt static-musl binaries (amd64, arm64, armv7) are attached to each release, with a SHA256SUMS file to verify them (sha256sum -c SHA256SUMS). From source: clone the repo and run just build (binary at target/release/freshdock).

Update modes

ModeBehaviour
livePoll frequently; pull and recreate on every new digest.
nightly / weekly / monthlyCheck on a cron schedule (default 04:00); recreate if newer.
watchDetect updates and notify only, never pull or restart.
offNever updated. Still listed by freshdock check.

Set the mode (and an optional cron override) with labels:

    labels:
      - "freshdock.enable=true"
      - "freshdock.mode=weekly"
      - "freshdock.schedule=0 2 * * 1"   # 02:00 every Monday (overrides the default)

Full label vocabulary and cron syntax: Configuration and Scheduling.

Documentation

QuickstartUp and running in a minute.
ConfigurationEvery label, env var, and freshdock.toml table (the single source of truth).
CLI referencecheck, recreate, run, and all flags.
Scheduling & modesUpdate modes and cron syntax.
Compose projectsA stack updated as one unit: one-shot migrations, depends_on ordering.
NotificationsWebhook, Discord, Telegram, SMTP.
Health & rollbackThe recreate lifecycle and image cleanup.
Lifecycle hooksPre-update and post-update commands.
Registry authPrivate registries and credentials.
DeploymentContainer, systemd, socket permissions, compatibility.
TroubleshootingSymptom-first fixes for common first-run issues.
Migrating from WatchtowerLabel/flag translation.
Architecture & roadmapDesign, phases, goals, risks.

Runnable example stacks: examples/compose/. A commented config template: freshdock.toml.example.

Why freshdock

Watchtower was the de-facto Docker auto-updater for years. Its maintainers archived it on 17 December 2025, and it shipped an embedded Docker SDK (API 1.25) incompatible with Docker Engine 29+. The community has forks, but none combine what matters for a small homelab:

  1. Modern Docker API: the API version is negotiated with your daemon at connect time via bollard, so freshdock speaks the newest API that daemon supports.
  2. Safe updates: a broken new image rolls back automatically instead of leaving a dead container.
  3. Small footprint: a single static binary, not a 100+ MB image to manage your other containers.

Compatibility

PlatformStatus
Plain DockerPrimary target. The API version is negotiated per daemon; CI exercises the Docker engine shipped on GitHub's ubuntu-latest runners.
Docker Desktop (Linux, macOS, Windows)Supported.
Portainer (CE and Business)Supported via the same Docker socket.
Podman 4+Supported via the Docker-compatible socket.
Docker ComposeA project is updated as one unit: one-shot service_completed_successfully services are re-run first, the rest follow in depends_on order. Compose files are never read or written.
Compose-based UIs (Dockge, Komodo, and similar)Supported; the compose files themselves are untouched.
Kubernetes / SwarmOut of scope. Use platform-native mechanisms.

Socket discovery order, Podman paths, and the Docker API 1.44 floor for containers on more than one network are covered in Deployment.

Status & roadmap

Phases 0-7 are complete and freshdock has been stable since 1.0.0. The full plan and architecture live in the roadmap; release mechanics in RELEASE.md; per-version notes in CHANGELOG.md.

Contributing

Contributions are welcome. See CONTRIBUTING.md for local setup, the quality gates, and dependency hygiene. Security reports: SECURITY.md.

Support

freshdock is free and open source. If it keeps your homelab up to date, you can support its development through GitHub Sponsors. Sponsoring is optional; stars, bug reports, and pull requests help just as much.

License

freshdock is licensed under the Apache License 2.0.

Acknowledgements

  • Watchtower for being the standard for ten years and shaping the design space.
  • bollard for the Rust Docker SDK that makes any of this possible.

Contributors

Languages

Rust

99.5%