Container image update watcher — 23 registries, 20 notification and action providers.
English · Español · Polski · 简体中文 · Deutsch · Français · Português (Brasil)
Warning
Updating from an older release? Read the upgrade notes first. Three security-hardening fixes first shipped in 1.4.6 and run through the entire 1.5 line, so anyone updating from a release older than 1.4.6 is affected whatever version they land on (1.4.6, any 1.5.x, or later). They are not deprecations and have no grace period: OIDC now requires authorization_endpoint in your provider's discovery metadata, unauthenticated rate-limiting keys on the TCP peer address (shared bucket behind a reverse proxy), and HTTP-trigger proxy URLs must use http(s)://. See UPGRADE-NOTES.md before updating.
- 📖 Documentation
- 🚀 Quick Start
- 🆕 Recent Updates
- 📸 Screenshots & Live Demo
- 🤔 Why Drydock
- ✨ Features
- 🔌 Supported Integrations
- ⚖️ Feature Comparison
- 🔄 Migration
- 🗺️ Roadmap
- ⭐ Star History
- 🔧 Built With
- 🤝 Community QA
Recommended: use a socket proxy to restrict which Docker API endpoints Drydock can access. This avoids giving the container full access to the Docker socket.
services:
drydock:
image: codeswhat/drydock
depends_on:
socket-proxy:
condition: service_healthy
environment:
- DD_WATCHER_LOCAL_HOST=socket-proxy
- DD_WATCHER_LOCAL_PORT=2375
- DD_AUTH_BASIC_ADMIN_USER=admin
- "DD_AUTH_BASIC_ADMIN_HASH=<paste-argon2id-hash>"
ports:
- 3000:3000
socket-proxy:
image: tecnativa/docker-socket-proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- CONTAINERS=1
- IMAGES=1
- EVENTS=1
- SERVICES=1
- INFO=1 # Required for daemon identity detection (notification prefixes)
# Add POST=1 and NETWORKS=1 for container actions and auto-updates
healthcheck:
test: wget --spider http://localhost:2375/version || exit 1
interval: 5s
timeout: 3s
retries: 3
start_period: 5s
restart: unless-stoppedAlternative: sockguard socket proxy
sockguard is a default-deny Docker socket filter from the same CodesWhat ecosystem, with a preset built for drydock:
services:
drydock:
image: codeswhat/drydock
depends_on:
sockguard:
condition: service_healthy
environment:
- DD_WATCHER_LOCAL_HOST=sockguard
- DD_WATCHER_LOCAL_PORT=2375
- DD_AUTH_BASIC_ADMIN_USER=admin
- "DD_AUTH_BASIC_ADMIN_HASH=<paste-argon2id-hash>"
ports:
- 3000:3000
sockguard:
image: codeswhat/sockguard
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./sockguard.yaml:/etc/sockguard/config.yaml:ro
environment:
- SOCKGUARD_CONFIG_FILE=/etc/sockguard/config.yaml
healthcheck:
test: wget --spider http://localhost:2375/version || exit 1
interval: 5s
timeout: 3s
retries: 3
start_period: 5s
restart: unless-stoppedSee sockguard's app/configs/portwing.yaml preset for a starting sockguard.yaml (the same preset portwing ships in its own examples).
Alternative: quick start with direct socket mount
docker run -d \
--name drydock \
-p 3000:3000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-e DD_AUTH_BASIC_ADMIN_USER=admin \
-e "DD_AUTH_BASIC_ADMIN_HASH=<paste-argon2id-hash>" \
codeswhat/drydock:latestWarning: Direct socket access grants the container full control over the Docker daemon. Use the socket proxy setup above for production deployments. See the Docker Socket Security guide for all options including remote TLS and rootless Docker.
Generate a password hash (
argon2CLI — install via your package manager):echo -n "yourpassword" | argon2 $(openssl rand -base64 32) -id -m 16 -t 3 -p 4 -l 64 -eOr with Node.js 24.7+ (no extra packages needed):
node -e 'const c=require("node:crypto");const s=c.randomBytes(32);const h=c.argon2Sync("argon2id",{message:process.argv[1],nonce:s,memory:65536,passes:3,parallelism:4,tagLength:64});console.log("argon2id$65536$3$4$"+s.toString("base64")+"$"+h.toString("base64"));' "yourpassword"Drydock v1.6 accepts only argon2id Basic auth hashes. Legacy
{SHA},$apr1$/$1$,crypt, and plain-text hashes are rejected; regenerate them before upgrading. Authentication is required by default. See the auth docs for OIDC, anonymous access, and other options. To explicitly allow anonymous access on fresh installs, setDD_ANONYMOUS_AUTH_CONFIRM=true.
The image includes trivy and cosign binaries for local vulnerability scanning and image verification.
See the Quick Start guide for Docker Compose, socket security, reverse proxy, and alternative registries.
v1.6.0-rc.2 highlights
- Notifications — Per-rule/per-provider title and body templates with live preview, plus audit-backed in-app bell categories and update severity thresholds.
- Dashboard — Zero-dependency CSS Grid replacement with mouse/touch reorder, bounded resize, responsive layouts, widget visibility, reset, and optional cross-device preference sync.
- Update policy — Declarative watcher/label/UI precedence, override/revert audit trail, maturity countdown/manual override, and pinned-tag informational visibility with a stacked current → newer Tag view.
- Performance & recovery — Per-poll tag-list deduplication, lighter aggregate projections, virtualized large log histories, immutable live-log rollover, auth-bootstrap timeout, complete preference migrations, and stale-chunk self-healing.
- v1.6 migrations enforced — WUD env/label aliases, legacy auth formats, obsolete watcher switches, template aliases, Kafka
clientId, and malformed token-only Hub/DHI public configs no longer run. The trigger-taxonomy aliases remain for one final error-level warning release.
Full migration guidance in DEPRECATIONS.md.
v1.5.2 highlights
- Recreation-safe update policy — Maturity gates, skipped tags/digests, and snoozes now survive container recreation for local and remote-agent workloads.
- Pinned-tag reliability — Fully pinned tags detect same-tag digest rebuilds again, while the UI can show a non-actionable newer same-family tag without changing update or trigger behavior.
- Rollback recovery — Failed replacement creation, network attachment, or startup now cleans up the candidate before restoring the original container, and repeated failures cannot cascade through nested rollback renames.
- Safer container recreation — Daemon-assigned MAC addresses are no longer pinned onto replacements, while explicitly configured primary-network MAC addresses remain preserved.
- Quieter local-image polling — Locally built or loaded images with no registry digest skip remote lookups instead of generating recurring authorization errors.
Full history in CHANGELOG.md.
Spot an update, see exactly what changes, apply it. Backup, health check, and rollback handled.
| Light | Dark |
![]() |
![]() |
Why look at screenshots when you can experience it yourself?
Fully interactive — real UI, mock data, no install required. Runs entirely in-browser.
Container images drift out of date silently. A base image patches a CVE, an app cuts a release, a tag moves. Unless you're watching every registry by hand, your running containers fall behind until something breaks or gets exploited.
Most tools force a tradeoff. The auto-updaters (Watchtower, Ouroboros) pull and restart with little visibility or control, and are now largely unmaintained. The dashboards (Portainer) manage containers but aren't built for update intelligence. Drydock is monitor-first: it watches 23 registries and tells you exactly what changed (major, minor, patch, or digest) before anything happens, then acts only when you let it. And it goes further than any of them. Trivy/Grype vulnerability scanning blocks unsafe updates, cosign verifies signatures, pre-update image backups roll back automatically on health-check failure, distributed agents cover remote hosts, and 20 notification and action integrations close the loop. The full update lifecycle, with a web UI and a REST API.
| Feature | Description | |
|---|---|---|
| 🔭 | Monitor-First Detection | Watches every running container and classifies each available update as major, minor, patch, or digest before anything happens. Nothing changes until you say so. |
| 📦 | 23 Registry Providers | Docker Hub, GHCR, ECR, ACR, GCR, GAR, GitLab, Quay, Harbor, Artifactory, Nexus, and 12 more. Public and private, cloud and self-hosted, with per-registry TLS and auth. |
| 🔔 | 20 Triggers | 17 notification channels (Slack, Discord, Telegram, Teams, SMTP, MQTT, ntfy, and more) plus Docker, Docker Compose, and Command actions, with per-event/provider templates, live preview, threshold filtering, and batch mode. |
| 🥊 | Update Bouncer | Trivy/Grype vulnerability scanning blocks unsafe updates before they deploy, with cosign signature verification and SBOM generation (CycloneDX and SPDX). |
| ↩️ | Image Backup & Auto Rollback | Pre-update image snapshots with configurable retention, automatic rollback on health-check failure, and one-click manual rollback from the UI. |
| 🪝 | Lifecycle Hooks | Pre and post-update shell commands via container labels, with per-hook timeouts and abort-on-failure control. |
| 🗂️ | Docker Compose Updates | Pull and recreate Compose services through the Docker Engine API with YAML-preserving image patching. |
| 🎛️ | Per-Container Policy | Regex tag rules and trigger routing use dd.* labels; maturity gates, skip/snooze/pin, and maintenance windows are stored via UI/API or watcher configuration. |
| 🛰️ | Distributed Agents | Monitor remote Docker hosts over SSE. Edge agents behind NAT dial out over WebSocket with Ed25519 key auth, no inbound port required (DD_EXPERIMENTAL_PORTWING=true). |
| 🖥️ | Web Dashboard | Vue 3 UI with a zero-dependency customizable widget grid, responsive table/card views, live SSE updates, notification-bell controls, and per-container detail, logs, and stats. |
| 🔗 | REST API & Webhooks | Token-authenticated endpoints for CI/CD watch and update triggers, plus signed registry webhook ingestion for push events. |
| 🔐 | OIDC Authentication | Secure the dashboard with OpenID Connect (Authelia, Auth0, Authentik). All auth flows fail closed by default. |
| 📈 | Prometheus Metrics | Built-in /metrics endpoint with optional auth bypass for Prometheus and Grafana monitoring stacks. |
| 🌍 | 17 UI Locales | Fully wired translation system with English complete and 16 community-maintained locales synced through Crowdin, switchable in Config. |
| 🔒 | ReDoS-Immune Regex | Every user-supplied tag pattern compiles via re2js (a pure-JS RE2 port) for linear-time matching that can't be stalled by a catastrophic-backtracking pattern. |
Docker Hub · GHCR · ECR · ACR · GCR · GAR · GitLab · Quay · LSCR · Harbor · Artifactory · Nexus · Gitea · Forgejo · Codeberg · MAU · TrueForge · Custom · DOCR · DHI · IBM Cloud · Oracle Cloud · Alibaba Cloud
Docker · Docker Compose · Command
Apprise · Discord · Google Chat · Gotify · HTTP · IFTTT · Kafka · Matrix · Mattermost · MQTT · MS Teams · NTFY · Pushover · Rocket.Chat · Slack · SMTP · Telegram
Anonymous (opt-in via DD_ANONYMOUS_AUTH_CONFIRM=true) · Basic (username + password hash) · OIDC (Authelia, Auth0, Authentik). All auth flows fail closed by default.
Trivy- or Grype-powered vulnerability scanning blocks unsafe updates before they deploy. Includes cosign signature verification and SBOM generation (CycloneDX & SPDX).
How does drydock compare to other container update tools?
✅ = supported ❌ = not supported
⚠️ = partial / limited † = archived, no longer maintained
| Feature | drydock | WUD | Diun | Watchtower † | Ouroboros † |
|---|---|---|---|---|---|
| Web UI / Dashboard | ✅ | ✅ | ❌ | ❌ | ❌ |
| Auto-update containers | ✅ | ✅ | ❌ | ✅ | ✅ |
| Docker Compose updates | ✅ | ✅ | ❌ | ❌ | |
| Trigger / notification channels | 20 | 16 | 17 | ~19 | ~6 |
| Registry providers | 23 | 13 | |||
| OIDC / SSO authentication | ✅ | ✅ | ❌ | ❌ | ❌ |
| REST API | ✅ | ✅ | ❌ | ||
| Prometheus metrics | ✅ | ✅ | ❌ | ✅ | ✅ |
| MQTT / Home Assistant | ✅ | ✅ | ✅ | ❌ | ❌ |
| Image backup & rollback | ✅ | ❌ | ❌ | ❌ | ❌ |
| Container grouping / stacks | ✅ | ✅ | ❌ | ❌ | |
| Lifecycle hooks (pre/post) | ✅ | ❌ | ❌ | ✅ | ❌ |
| Webhook API for CI/CD | ✅ | ❌ | ❌ | ✅ | ❌ |
| Container start/stop/restart/update | ✅ | ❌ | ❌ | ❌ | ❌ |
| Distributed agents (remote) | ✅ | ❌ | ✅ | ❌ | |
| Audit log | ✅ | ❌ | ❌ | ❌ | ❌ |
| Security scanning (Trivy/Grype) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Semver-aware updates | ✅ | ✅ | ✅ | ❌ | ❌ |
| Digest watching | ✅ | ✅ | ✅ | ✅ | ✅ |
| Multi-arch (amd64/arm64) | ✅ | ✅ | ✅ | ✅ | ✅ |
| Container log viewer | ✅ | ❌ | ❌ | ❌ | ❌ |
| Actively maintained | ✅ | ✅ | ✅ | ❌ | ❌ |
Data based on publicly available documentation as of March 2026. Contributions welcome if any information is inaccurate.
Migrating from WUD (What's Up Docker?)
Drydock v1.6 no longer loads WUD_* environment variables or wud.* labels at runtime. Rewrite them before starting the upgraded service; persisted state still migrates automatically. Use docker exec -it drydock node dist/index.js config migrate --dry-run to preview, then docker exec -it drydock node dist/index.js config migrate --file .env --file compose.yaml to rewrite configuration to DD_* and dd.* naming.
Version themes & highlights
High-level themes only — see CHANGELOG.md for per-release detail.
| Version | Theme | Highlights |
|---|---|---|
| v1.3.x ✅ | Security & Stability | Trivy scanning, Update Bouncer, SBOM, 7 new registries, 4 new triggers, re2js regex engine |
| v1.4.x ✅ | UI Modernization & Hardening | Tailwind 4 + custom components, 6 themes, Cmd/K palette, OpenAPI 3.1, compose-native YAML updates, dual-slot scanning, OIDC hardening |
| v1.5.0 ✅ | Observability & i18n | trigger taxonomy split (DD_ACTION_*/DD_NOTIFICATION_*), WebSocket log viewer, dashboard customization, resource monitoring, notification outbox + DLQ, security scan digest, 17 locales, SSE Last-Event-ID replay, edge agent dial-out with Ed25519 auth (experimental, DD_EXPERIMENTAL_PORTWING=true) |
| v1.5.1 ✅ | Security & Maintenance | GCR/GAR pull-auth fix, registry TLS completion (M-2), hook env-var injection hardening, DD_SESSION_SECRET__FILE support, debug-dump credential redaction, secret-file permission check, maturity gate deadlock fix, full UI translatability + community translations, maintenance-window auto-apply gate, container uptime display, Tag/Version column split surfacing software version (OCI label, with dd.inspect.tag.path dual-write + opt-in dd.inspect.tag.version-only routing), opt-in compose mount-prefix matching, ${currentReleaseNotes} template var |
| v1.5.2 ✅ | Policy & Pinned-Tag Reliability | Recreation-safe maturity/skip/snooze policy retention, pinned-tag digest rebuild detection and informational same-family insights, rollback-candidate cleanup, rollback-cascade prevention, explicit-MAC preservation, and local-image registry-skip behavior |
| v1.6.0 | Notifications, Policy & Release Intel | Per-rule/per-trigger notification templates with live preview, notification-bell preferences, cross-device preference sync, zero-dependency custom dashboard grid (#281), declarative update policy (#320), maturity stabilization countdown + immediate candidate visibility + manual override (#406), actionable Update Status panel and global notify / manual / auto update mode (#325), watcher/imgset/container tag-policy inheritance plus stacked current → newer pinned-tag visibility (#498), standardized 44px Source / release notes / registry resource actions across table, cards, and details (#295), health-status event notifications (#198), bidirectional Home Assistant MQTT, responsive table/card list views, Trivy/Grype/both scanning across command or pinned Docker-worker backends, scanner asset pull/warm controls, off-heap deduplicated SBOM storage, Trivy long-scan correctness (#490), trigger-taxonomy migration warnings, v1.6 compatibility removals, docs/API hygiene, and /api → /api/v1 migration completion with an opt-in wud-card/Homepage compatibility shim (DD_COMPAT_WUDCARD). |
| v1.7.0 | Smart Updates & UX | Dependency-aware ordering (#219), selective bulk updates (#232), per-action update policy (#511), image prune, static image monitoring, image maturity indicator, unified maturity/update-age clock, clickable port links, keyboard shortcuts, PWA, DD_TRIGGER_* removal (end of the v1.5.0 deprecation window), curl removed from the image |
| v1.8.0 | Fleet Management & Live Config | YAML config, live UI config, volume browser, parallel updates, SQLite store migration |
| v2.0+ | Platform Expansion & Beyond | Swarm/Kubernetes watchers, GitOps, health gates, canary deploys, web terminal, RBAC, scoped rotatable API keys (static bearer tokens for HA/dashboard integrations, #469), LDAP/AD, native Podman provider beyond the Docker-compatible API, CLI, Wolfi hardened image, socket proxy |
| Resource | Link |
|---|---|
| Website | getdrydock.com |
| Live Demo | demo.getdrydock.com |
| Docs | getdrydock.com/docs |
| Configuration | Configuration |
| Quick Start | Quick Start |
| Changelog | CHANGELOG.md |
| Deprecations | DEPRECATIONS.md |
| Roadmap | See Roadmap section above |
| Contributing | CONTRIBUTING.md |
| Issues | GitHub Issues |
| Discussions | GitHub Discussions — feature requests & ideas welcome |
Questions, feedback, and early support: CodesWhat Discord
Please file concrete bugs and feature requests in GitHub Issues so they do not get lost in chat.
Thanks to the users who helped test v1.4.0 and v1.5.0 release candidates and reported bugs:
@RK62 · @flederohr · @rj10rd · @larueli · @Waler · @ElVit · @nchieffo · @begunfx · @Ra72xx
| Tool | Role |
|---|---|
| drydock | Container update monitoring — web UI and notification engine |
| portwing | Remote Docker agent — secure socket-level access from Drydock or standalone |
| sockguard | Docker socket proxy — default-deny allowlist filter protecting the socket |
These three tools are designed to layer: sockguard filters the socket, portwing exposes it remotely, and drydock monitors and acts on container state.
See portwing's COMPATIBILITY.md for the full compatibility matrix across all three tools.


