No description
  • Python 68%
  • TypeScript 22.3%
  • Shell 5.6%
  • CSS 3.5%
  • Dockerfile 0.2%
  • Other 0.3%
Find a file
2026-06-11 15:42:22 +02:00
containers release: set management version to v0.2.0 (BUILD 0) 2026-06-08 16:06:22 +02:00
docs docs: comprehensive v0.2.0 changelog (audit, host pause, self-maintenance, safe apply, …) 2026-06-08 15:36:23 +02:00
scripts feat: version the agent independently of the management server 2026-06-08 12:28:39 +02:00
stack chore: point stack compose at forgejo registry (prod pulls from main) 2026-06-11 15:42:22 +02:00
.gitignore feat: use container logo as favicon and in the README 2026-06-08 11:57:03 +02:00
build-and-push.sh build: fork build-and-push.sh — tag drydock-agent with its own version, disable self-update 2026-06-08 16:06:11 +02:00
build.sh Project basis: build/push tooling, build-version templates, changelog convention from shared-integrations 2026-06-07 11:52:23 +02:00
CLAUDE.md feat: store external Basic Auth encrypted in settings 2026-06-08 13:09:30 +02:00
README.md feat: use container logo as favicon and in the README 2026-06-08 11:57:03 +02:00

Drydock logo

Drydock

🤖 AI-written project. This entire repository — code, documentation, and this README — is written by an AI agent (Claude Code) under human direction. Treat it accordingly: review before relying on it in production.

A self-hosted, Watchtower-style container update tool for a multi-host Docker homelab, with a central UI and the per-container control Watchtower lacks. It replaces Watchtower (archived December 2025) and What's Up Docker.

What it does

The running container is the source of truth. There is no git, no compose files, and no repo access anywhere in the runtime. A lightweight agent on each host reads the running containers from the Docker socket, reports them as inventory, and checks the registry for newer upstream images. On an approved update it pulls the new image and recreates the container with the same config on the new image, then prunes — exactly Watchtower's mechanism, plus a central multi-host UI.

Update modes

Each container's effective mode is its own override, or the global default (approve by default):

mode on a detected update…
auto pull + recreate automatically (Watchtower behavior)
monitor notify only, never act
approve land in the approval queue — apply when you say so

Digest watch (same tag, new digest) is always on. Semver watch (newer version tags) is opt-in, per container with a global default.

Architecture

Two images are built from this repository:

  • ivooskamp/drydock — the management server: a single container running FastAPI that serves the built React UI. It has its own Postgres in the same Docker stack.
  • ivooskamp/drydock-agent — a per-host agent with Docker socket access. It is a pure executor: it reports what runs and runs the jobs it is handed; it decides nothing.

All connections are outbound from agent to management — the management server never connects to an agent. The web UI and full API are internal only; only the locked-down /agent/ endpoint is exposed publicly (IP allow-list plus a per-agent token over public HTTPS). This is what keeps an untrusted host (e.g. a seedbox) contained.

Repository layout

drydock/
├── CLAUDE.md                     ← context for the AI agent working on this repo
├── build.sh                      ← version-aware build wrapper: ./build.sh t | r
├── build-and-push.sh             ← shared Docker build & push script
├── scripts/                      ← version tooling (bump/check/set release version)
├── stack/                        ← docker-compose for the management server and the agent
├── containers/
│   ├── drydock/                  ← management server (FastAPI + built React)
│   │   └── app/version.py        ← VERSION / BUILD source of truth
│   └── drydock-agent/            ← per-host agent
└── docs/
    ├── design-spec.md            ← the full design specification (read this first)
    ├── deployment.md             ← deployment notes
    ├── changelog-develop.md      ← append-only development log
    └── changelog.md              ← release summary

Configuration

Only DATABASE_URL lives in environment variables. Everything else (registries, hosts, update modes, poll interval, scope) is stored in the database and managed through the settings UI. Migrations use Alembic.

Build & release

  • ./build.sh t — bump the dev build number, build & push the :dev images, push the dev branch.
  • ./build.sh r — validate version state and release from main: merge dev, tag vX.Y.Z, push, then recreate the dev branch.

Versions are committed source state, not derived from git: a dev image is visibly v0.1.0.22 rather than an ambiguous re-pushed v0.1.0.

Status

Early development (v0.1.0). See docs/design-spec.md for the full design and docs/changelog.md for what has shipped.