README.md

May 7, 2026 Β· View on GitHub

Important

Trivy Supply Chain Compromise (GHSA-69fq-xp46-6x23): Drydock is not affected. We do not use the compromised GitHub Actions, the bundled Trivy binary is pinned to a safe version (v0.69.3), and all CI actions are SHA-pinned. No compromised code was ever pulled or shipped. Full advisory β†’

drydock

drydock

Open source container update monitoring β€” built in TypeScript with modern tooling.

Version GHCR pulls Docker Hub pulls Quay.io
Multi-arch Image size License AGPL-3.0

Stars Forks Issues Last commit Commit activity
Discussions Repo size Repo views Mentioned in Awesome Docker Crowdin

CI OpenSSF Best Practices OpenSSF Scorecard
Codecov Mutation testing Maintainability Monitored by Snyk


πŸ“‘ Contents


πŸš€ Quick Start

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
      # 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-stopped
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:latest

Warning: 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 (argon2 CLI β€” install via your package manager):

echo -n "yourpassword" | argon2 $(openssl rand -base64 32) -id -m 16 -t 3 -p 4 -l 64 -e

Or with Node.js 24+ (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"

Legacy v1.3.9 Basic auth hashes ({SHA}, $apr1$/$1$, crypt, and plain) are accepted for upgrade compatibility but deprecated (removed in v1.6.0). Argon2id is recommended for all new configurations. Authentication is required by default. See the auth docs for OIDC, anonymous access, and other options. To explicitly allow anonymous access on fresh installs, set DD_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.


πŸ†• Recent Updates

  • Chinese UI locales β€” First non-English locale set: Simplified Chinese and Traditional Chinese, with 1,100+ translated strings across every view, contributed by TianMiao (PR #331, PR #344). Switch languages in Config > Appearance. The i18n framework is ready for additional locales, and Crowdin sync is configured for translation PRs.
  • Multi-select audit log filter β€” The event-type filter in the Audit Log view is now a checkbox dropdown so you can view any combination of event categories (e.g. update-applied + update-failed) in one query. The backend ?actions= parameter was already there; the UI now exposes it. (discussion #332)
  • Credential redaction expanded β€” update-failed SSE error payloads now redact x-registry-auth, *-token, and api-key fields in addition to Authorization headers, so registry credentials and API keys no longer leak in operator-visible diagnostics.
  • Update eligibility blockers β€” Container rows now surface structured pre-flight blockers inline (maturity hold, security block, maintenance window, policy exclusion, pinned version) so you can see exactly why an update button is disabled without opening the detail panel.
  • Scan vs. update row status β€” Container rows correctly distinguish a scan-in-progress state from an update-in-progress state, so the row badge matches the actual operation type.
  • Expand / Collapse all stacks β€” A single toolbar button expands or collapses every stack group at once when Stack view is enabled; the label reflects the current global expand state. Individual stack headers still toggle independently. (#311)
  • Dashboard + Containers view reconnect performance β€” On SSE reconnect, both views now refetch only endpoints that can go stale (skipping static ones for 30s) and patch the local container array in place instead of replacing it. On large inventories this turns a reconnect storm into a handful of requests and eliminates the post-reconnect flicker. (#301)
  • Security scan digest mode β€” SECURITYMODE=digest (or batch+digest) sends one severity-grouped summary per scan cycle instead of one notification per vulnerable container. New bulk POST /api/v1/containers/scan-all endpoint scans the whole fleet server-side and emits a single security-scan-cycle-complete event; the UI Scan All button now uses it so a 40-container inventory produces one email instead of forty. (#300)
  • Notification dropdown rework β€” The bell dropdown gains per-row βœ• dismiss, a header Clear bulk action, and a split footer (Mark all as read / Open audit log). New --dd-zebra-stripe theme token keeps alternate rows legible on every stock theme. (#267)
  • Actionable deprecation banners β€” Every deprecation warning now carries the concrete migration action inline plus a "View migration guide" link that deep-jumps to the relevant anchor on the deprecations doc. (#214)
  • Per-channel notification dedup β€” The batch and digest notification channels now track once=true dedup independently, so MODE=batch+digest reliably delivers both the immediate batch email and the scheduled morning digest for each detected update.
  • Container list performance β€” GET /api/containers now preloads active update operations in a single indexed scan with per-row O(1) lookup, eliminating the rc.8 slowdown on large inventories (Dashboard / Watchers / Servers / Container Logs all benefit).
  • Persistent once-dedup β€” once=true notification dedup survives process restarts and transient changed=false scan cycles via a new on-disk notification history store, so notifications no longer re-fire after a restart.
  • Hide Pinned surfaces actionable rows β€” Pinned containers with a pending update stay visible when Hide Pinned is on; only static pinned rows are hidden, matching the decluttering intent without suppressing actionable updates.
  • Remote-agent updates work end-to-end β€” Controller trims the remote-trigger payload for docker / dockercompose updates so the agent's json body cap can't block an update with HTTP 413.
  • Socket-proxy identity detection β€” Daemon host-name detection now runs for host-based watchers (TCP to a local socket-proxy, the common Synology / Compose pattern), so notification prefixes stop falling back to container short IDs.
  • Backend-driven update queue β€” Container updates queued server-side with per-trigger concurrency limits. UI shows Queued β†’ Updating β†’ Updated progression with sequence labels (e.g. "Updating 1 of 3"). Global cap configurable via DD_UPDATE_MAX_CONCURRENT (default 0 = unlimited; set to a positive integer to bound how many updates run simultaneously across the whole controller instance).
  • Identity-keyed container tracking β€” Containers tracked by stable identity key (agent::watcher::name) across renames/replacements, preventing cross-host status contamination.
  • Watcher next-run schedule visibility β€” Watcher API and Agents view now show when each watcher will next poll for updates.
  • Notification delivery failure audit trail β€” Failed notification deliveries surface in the notification bell dropdown for visibility without leaving the UI.
  • Multi-server notification identification β€” Notifications automatically include [server-name] prefix when agents are registered, identifying which server each update comes from. Configurable via DD_SERVER_NAME (defaults to the detected daemon host name, then the process hostname). Custom templates can use container.notificationServerName.
  • System log viewer overhaul β€” Pinned toolbar, line wrapping, sort toggle (newest/oldest), filter mode (funnel icon shows matches only), auto-apply filters, component dropdown from API, aligned columns, floating copy button.
  • Hide Pinned containers β€” Checkbox toggle in the container filter bar hides version-pinned containers. Persisted in user preferences.
  • Combined batch+digest notifications β€” MODE=batch+digest sends both immediate batch emails and scheduled digest summaries.
  • Multi-host same-name container support β€” Containers with identical names across different hosts no longer collide in the UI. Actions, logs, and detail panels route by container ID.
  • Lazy OIDC discovery β€” SSO provider startup failures no longer block the server. Discovery retries on first use.

πŸ“Έ Screenshots & Live Demo

Light Dark
Dashboard Light Dashboard Dark

Why look at screenshots when you can experience it yourself?

Try the Live Demo

Fully interactive β€” real UI, mock data, no install required. Runs entirely in-browser.


✨ Features

Container Monitoring

Auto-detect running containers and check for image updates across registries

20 Notification Triggers

Slack, Discord, Telegram, Teams, Matrix, SMTP, MQTT, HTTP webhooks, Gotify, NTFY, and more

23 Registry Providers

Docker Hub, GHCR, ECR, GCR, GAR, GitLab, Quay, Harbor, Artifactory, Nexus, and more

Docker Compose Updates

Auto-pull and recreate services via Docker Engine API with YAML-preserving service-scoped image patching

Distributed Agents

Monitor remote Docker hosts with SSE-based agent architecture

Audit Log

Event-based audit trail with persistent storage, REST API, and Prometheus counter

OIDC Authentication

Authelia, Auth0, Authentik β€” secure your dashboard with OpenID Connect

Prometheus Metrics

Built-in /metrics endpoint with optional auth bypass for monitoring stacks

Image Backup & Rollback

Automatic pre-update image backup with configurable retention and one-click rollback

Container Actions

Start, stop, restart, and update containers from the UI or API with feature-flag control

Webhook API

Token-authenticated CI/CD endpoints for watch/update actions plus signed registry webhook ingestion for push events

Container Grouping

Smart stack detection via compose project or labels with collapsible groups and batch-update

Digest Notifications

Batch update events over a schedule with trigger `MODE=digest` and configurable digest cron windows

System Log Streaming

Real-time WebSocket system log view in the UI with shared log viewer components

Advanced List API

Container list supports queryable sort/order, watched-kind, runtime status, watcher, and maturity filters

Lifecycle Hooks

Pre/post-update shell commands via container labels with configurable timeout and abort control

Auto Rollback

Automatic rollback on health check failure with configurable monitoring window and interval

Graceful Self-Update

DVD-style animated overlay during drydock's own container update with auto-reconnect

Icon CDN

Auto-resolved container icons via selfhst/icons with homarr-labs fallback and bundled selfhst seeds for internetless startup

Mobile Responsive

Fully responsive dashboard with optimized mobile breakpoints for all views

Multi-Registry Publishing

Available on GHCR, Docker Hub, and Quay.io for flexible deployment

πŸ”Œ Supported Integrations

πŸ“¦ Registries (23)

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

πŸ”” Triggers (20)

Apprise Β· Command Β· Discord Β· Docker Β· Docker Compose Β· Google Chat Β· Gotify Β· HTTP Β· IFTTT Β· Kafka Β· Matrix Β· Mattermost Β· MQTT Β· MS Teams Β· NTFY Β· Pushover Β· Rocket.Chat Β· Slack Β· SMTP Β· Telegram

πŸ” Authentication

Anonymous (opt-in via DD_ANONYMOUS_AUTH_CONFIRM=true) Β· Basic (username + password hash) Β· OIDC (Authelia, Auth0, Authentik). All auth flows fail closed by default.

API note: POST /api/v1/containers/:id/env/reveal is currently scoped to authentication only (no per-container RBAC yet), so any authenticated user is treated as a trusted operator for secret reveal actions. The unversioned /api/containers/:id/env/reveal alias remains available during the API-version transition.

OpenAPI note: machine-readable API docs are available at GET /api/v1/openapi.json (canonical) and GET /api/openapi.json (compatibility alias during transition).

API versioning note: third-party integrations should migrate to /api/v1/*. The unversioned /api/* alias is deprecated and will be removed in v1.6.0.

πŸ₯Š Update Bouncer

Trivy-powered vulnerability scanning blocks unsafe updates before they deploy. Includes cosign signature verification and SBOM generation (CycloneDX & SPDX).


βš–οΈ Feature Comparison

How does drydock compare to other container update tools?

βœ… = supported Β  ❌ = not supported Β  ⚠️ = partial / limited Β  For the full itemized changelog, see CHANGELOG.md.

Feature drydock WUD Diun Watchtower † Ouroboros †
Web UI / Dashboardβœ…βœ…βŒβŒβŒ
Auto-update containersβœ…βœ…βŒβœ…βœ…
Docker Compose updatesβœ…βœ…βŒβš οΈβŒ
Notification triggers201617~19~6
Registry providers2313⚠️⚠️⚠️
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)βœ…βŒβŒβŒβŒ
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.


πŸ”„ Migration

Migrating from WUD (What's Up Docker?)

Drop-in replacement β€” swap the image, restart, done. All WUD_* env vars and wud.* labels are auto-mapped at startup. State file migrates automatically. Use config migrate --dry-run to preview, then config migrate --file .env --file compose.yaml to rewrite config to drydock naming.


πŸ—ΊοΈ Roadmap

VersionThemeHighlights
v1.3.x βœ…Security & StabilityTrivy scanning, Update Bouncer, SBOM, 7 new registries, 4 new triggers, rollback fixes, GHCR auth, self-hosted TLS, re2js regex engine, compose trigger fixes, DB persistence on shutdown
v1.4.0 βœ…UI Modernization & HardeningTailwind CSS 4 + custom component library, 6 themes, 7 icon libraries, font size preference, Cmd/K command palette, OpenAPI 3.1.0 endpoint, standardized API responses with pagination, compose-native YAML-preserving updates, rename-first rollback with health gates, self-update controller with SSE ack, fail-closed auth enforcement, OIDC redirect URL validation, tag-family semver, notification rules, container grouping by stack, audit history view, dual-slot security scanning, scheduled scans, WUD migration CLI, bundled offline icons, dashboard drag-reorder, gzip compression, API error sanitization, agent log validation, TLS path redaction, audit store indexing with 30-day retention, type-safe store modules, durable batch scans, recent-status API, advisory-only security scanning, compose trigger hardening (auto-detection, validation, reconciliation, digest pinning, batch mode, multi-file awareness), reactive server feature flags, identity-aware rate limiting, API hardening
v1.4.1 βœ…Patch & PolishHeadless mode (API-only), maturity-based update policy (NEW/MATURE badges), ?groupByStack=true URL param, agent handshake + SSE fix (#141), mangled hash detection + anonymous fallback + login error surfacing (#147), CSRF behind reverse proxies (#146), compose trigger affinity across remapped roots, CSP inline style elimination, connection-lost animation, LokiJS metadata stripping, timing side-channel fix, image hardening
v1.4.2 βœ…Bug FixesWatcher container count fix (#155), container recreate alias filtering (#156), stale store data fix (#157), CI versioned-only images (#154), maturity badge sizing, dependency upgrades
v1.4.3 βœ…DNS & SecurityConfigurable DNS result ordering for Alpine EAI_AGAIN fix (#161), Docker socket security guide, zizmor blocking in CI, scoped GitHub environments
v1.4.4 βœ…UI Polish & HardeningAlias dedup hardening with 30s transient window (#156), dashboard host-status for remote watchers (#155), tooltip viewport fix (#165), click-to-copy version tags (#164), Simple Icons dark mode inversion, theme switcher fix, search button polish, URL rebrand to getdrydock.com
v1.5.0Observability & User-Requested FeaturesReal-time WebSocket log viewer with ANSI colors + JSON syntax highlighting, dashboard customization (grid layout, drag, resize, widget visibility), container resource monitoring (CPU/memory stats + dashboard widget), diagnostic debug dump, registry webhook receiver, trigger env var aliases (DD_ACTION_*/DD_NOTIFICATION_*), digest notification mode, security scan digest (#300) with bulk scan-all endpoint and per-cycle event contract, design system components (WCAG touch targets, shared primitives), floating tag detection + auto digest watching, bearer token auth for /metrics, Podman API version negotiation, toast notifications for all container actions, UI standardization (margins, text sizes, deprecation banners), shared DataTable sizing with sticky actions, keyboard/touch resize, autosize, persisted per-view widths, and responsive Containers column hiding, source project shortcut link on containers (#295), next-check countdown + absolute tooltip on Watchers (#288), actionable deprecation banners with inline migration paths (#214), update eligibility blockers surfaced per-container row, SSE Last-Event-ID replay + resync, inline security-page update action (#299), expand/collapse all stacks toggle (#311), GET /update-operations/:id polling endpoint
v1.6.0Scanner Decoupling, Notifications & Release IntelBackend-based scanner execution (docker/remote), Grype provider, scanner asset lifecycle, scanner long-scan UX (heartbeat log every 30s during in-flight scans, default Trivy timeout 120s β†’ 600s, "Scanning…" pill on container rows while gate is in flight), custom zero-dependency dashboard grid (replaces grid-layout-plus, #281), table-only workflow polish on top of the shared DataTable foundation (slide-in side panel, stable row/detail behavior, virtualization follow-up); notification templates, release notes in notifications, notification preferences UI, cross-device preference sync, software version column, bidirectional MQTT for HA, declarative update policy (env + label + UI) with override tracking, UI table-only simplification (drop card + accordion view modes; standardize on table + slide-in side panel), Update Status Panel slide-in redesign + Update mode global setting (notify/manual/auto) (#325), store size investigation β€” SBOM off-heap storage + bounded audit dedup (dd.json bloat fix; root cause: inline SBOM documents on every container row Γ— 2 formats Γ— current+update images) (#321), dry-run UX surfacing (WARN-level log + UI pill + audit action) (#321), Preview Update typed error codes + deep-link guidance (#321), remove all deprecated compatibility aliases (see DEPRECATIONS.md)
v1.7.0Smart Updates & UXDependency-aware ordering, clickable port links, image prune, static image monitoring, image maturity indicator, keyboard shortcuts, container uptime display, PWA support, debounced container discovery
v1.8.0Fleet Management & Live ConfigYAML config, live UI config panels, volume browser, parallel updates, SQLite store migration + ID-based container identity, Crowdin integration (i18n framework shipped in v1.5; Simplified and Traditional Chinese locales bundled as of v1.5.0-rc.18)
v2.0.0Platform ExpansionDocker Swarm, Kubernetes watchers and triggers, basic GitOps
v2.1.0Advanced Deployment PatternsHealth check gates, canary deployments, durable self-update controller
v2.2.0Container OperationsWeb terminal, file browser, image building, basic Podman support
v2.3.0Automation & Developer ExperienceAPI keys, passkey auth, TOTP 2FA, TypeScript actions, CLI
v2.4.0Data Safety & TemplatesScheduled backups (S3, SFTP), compose templates, secret management
v3.0.0Advanced PlatformNetwork topology, GPU monitoring, full i18n translations + RTL
v3.1.0Enterprise Access & ComplianceRBAC, LDAP/AD, environment-scoped permissions, audit logging, Wolfi hardened image
v3.2.0Drydock Socket ProxyBuilt-in companion proxy container (allowlist-filtered Docker API), rootless Docker & remote TLS security docs

πŸ“– Documentation

ResourceLink
Websitegetdrydock.com
Live Demodemo.getdrydock.com
Docsgetdrydock.com/docs
ConfigurationConfiguration
Quick StartQuick Start
ChangelogCHANGELOG.md
DeprecationsDEPRECATIONS.md
RoadmapSee Roadmap section above
ContributingCONTRIBUTING.md
IssuesGitHub Issues
DiscussionsGitHub Discussions β€” feature requests & ideas welcome

Star History Chart

SemVer Conventional Commits Keep a Changelog

Built With

TypeScript Vue 3 Express 5 Vitest Biome Node 24 Docker Anthropic

Community QA

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


AGPL-3.0 License

CodesWhat

Ko-fi Buy Me a Coffee Sponsor

Back to top