A self-hosted web dashboard to manage the Docker containers of your server and keep them updated.
- Container overview: state, image and tag, network, IP / MAC, container and LAN ports, volumes, uptime, autostart. Right-click a container for every action
- Live resources: CPU and RAM refreshed every second, with the limits configured on each container; host CPU and RAM always visible in the header
- Health alerts: health check status on every container (healthy, unhealthy, starting) and notifications when a container becomes unhealthy, recovers, crashes or keeps restarting
- Update checks: check one or all containers and see the exact change (
4bbda4e -> 9f3c2d1); private registries supported (GHCR, Docker Hub, any registry) using yourdocker login. A background check runs when DockerUpdates starts and then on an interval you choose in Settings (it only marks updates: nothing is installed unless Auto-Update says so) - Automatic updates: global schedule (hourly, daily, weekly, monthly or cron) plus per-container schedules, "update" or "notify only", time zone aware, with an optional cooldown so only images published N days ago are installed
- Notifications: Discord (rich embeds), Telegram, ntfy and generic webhooks (HMAC signed), with a test button
- Update history per container, and image cleanup (after each update and/or on a schedule)
- Logs and console: live logs with filter and download, and an interactive shell inside any running container
- Self-update: DockerUpdates updates itself safely through a short-lived helper container
- Edit containers: name, image, network, auto-restart, memory limit slider, ports, volumes, environment variables and Extra parameters (
--cpus=1.5 --hostname=app …) validated as you type - Templates: every created or edited container is saved as a template; import / export as JSON
- Compose stacks: deploy a
docker-composefile from Add compose (with an optional.env), edit and redeploy it, and update its services withdocker compose pull+up -d. Stacks started elsewhere are grouped too. Each stack shows the CPU, RAM and ports of all its services, an autostart switch and a color you pick with a right-click - Dedicated LAN IPs (macvlan / ipvlan): enable it once in Settings (the server network is detected automatically, nothing to run on the host), then give containers a fixed IP with an availability check
- Bulk actions: start / stop / pause / resume all (DockerUpdates never stops or pauses itself)
- Custom order and folders: unlock the list to drag containers into place; hold one over another for a second to make a folder (like app icons on a phone) and drag containers in or out of it; name it, pick its color, update or start / stop it as one
- Icons: custom icon URL per image, or the app's favicon discovered automatically
- Admin Panel: active sessions (sign out any browser), failed logins, live server logs with the audit trail, login lockouts you can lift, an IP / CIDR ban list, and system information (app, image, Docker engine, data volume)
- Secure by default: login, revocable sessions, brute-force lockout with limits editable in Settings, strict same-origin API, CSP and security headers, audit log (SECURITY.md)
- Light / dark theme, search and filters, Linux and Windows (Docker Desktop) hosts
The full documentation is in the wiki (source in docs/wiki):
Installation · Configuration (every variable) · Settings · Automatic updates · Notifications · Reverse proxy · Private registries · LAN network · Admin Panel · Security · Troubleshooting
DockerUpdates runs as a container that talks to the host Docker daemon through its socket.
mkdir -p ~/dockerupdates/data && cd ~/dockerupdates
cat > .env <<EOF
ADMIN_USER=admin
ADMIN_PASSWORD=$(openssl rand -base64 18)
SESSION_SECRET=$(openssl rand -hex 32)
EOF
chmod 600 .env
cat .env # note your generated passwordDocker CLI
docker run -d --name dockerupdates --restart unless-stopped \
--env-file ~/dockerupdates/.env \
-p 3000:3000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.docker/config.json:/root/.docker/config.json:ro \
-v ~/dockerupdates/data:/app/backend/data \
--security-opt no-new-privileges \
ghcr.io/pixlgalaxy/dockerupdates:latestDocker Compose
services:
dockerupdates:
image: ghcr.io/pixlgalaxy/dockerupdates:latest
container_name: dockerupdates
restart: unless-stopped
env_file: .env
ports:
- "3000:3000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ~/.docker/config.json:/root/.docker/config.json:ro # optional: private registries
- ./data:/app/backend/data # settings, sessions, history, templates, icons
security_opt:
- no-new-privileges:trueOpen http://<server-ip>:3000 and sign in.
The data volume keeps settings, notification channels, update history, templates, icons and login sessions across updates. Without it, they are lost every time the container is recreated.
If
~/.docker/config.jsondoes not exist (you never randocker login), remove that volume line.
Stacks created with Add compose are saved in STACKS_DIR (default: data/stacks). Docker resolves relative paths in a compose file (./db:/var/lib/mysql) on the host, so to use them, mount a stacks folder at the same path on the host and in DockerUpdates:
environment:
- STACKS_DIR=/opt/stacks
volumes:
- /opt/stacks:/opt/stacksWithout it, stacks still work with named volumes and absolute host paths; a compose file with relative paths is refused with an explanation, so no data ends up in an unexpected folder.
All settings are environment variables (see backend/.env.example); each one is explained with examples in Configuration. Most of them can also be changed later in the web UI, in Settings > Account (username and password), Settings > Server & access and Settings > Registry credentials. A value saved in the UI takes precedence over .env.
| Variable | Required | Default | Description |
|---|---|---|---|
ADMIN_USER |
Yes | Login username | |
ADMIN_PASSWORD |
Yes | Login password. Default or < 8 character passwords are rejected; use 12+ | |
RESET_LOGIN_CONFIG |
false |
true deletes the username / password set in Settings > Account at startup, so ADMIN_USER / ADMIN_PASSWORD work again (forgotten login). Set it back to false afterwards |
|
SESSION_SECRET |
random | Signs session cookies, 32+ characters (openssl rand -hex 32) |
|
SESSION_HOURS |
12 |
Maximum session lifetime (initial value, then editable in Settings > Login & sessions) | |
SESSION_IDLE_MINUTES |
120 |
Sign out after this much inactivity (initial value, then editable in Settings) | |
PORT |
3000 |
HTTP port inside the container | |
HOST_IP |
auto | IP shown in the header and the LAN IP:Port links. Detected automatically (and kept up to date if it changes); set it only to pick another address of the server. A value that is not an address of the server is ignored with a warning in the server logs | |
HOST_NAME |
Docker host name | Server name shown in the header | |
REGISTRY_AUTH |
Registry credentials, e.g. ghcr.io=user:token,docker.io=user:token |
||
TRUST_PROXY |
private networks | IP of your reverse proxy (trusted for X-Forwarded-*) |
|
COOKIE_SECURE |
false |
true to always send the session cookie over HTTPS only |
|
ALLOWED_ORIGINS |
Extra origins allowed to call the API (normally not needed) | ||
CONSOLE_WS_KEEPALIVE |
0 (off) |
Seconds between pings on an open console, so a reverse proxy does not close it when idle (25 for Nginx Proxy Manager) |
|
DOCKER_HOST / DOCKER_SOCKET |
platform socket | Custom Docker connection |
Changes to .env apply when the container is recreated (docker rm -f + docker run, or docker compose up -d), not on docker restart: Docker copies the variables into the container when it is created. Settings changed in the web UI apply right away. PORT and the Docker connection can only be changed in .env.
To check and pull updates of private images, DockerUpdates needs registry credentials:
- Reuse your
docker login(recommended): rundocker login ghcr.ioon the host and mount~/.docker/config.jsonread-only, as in the quick start. - Or set
REGISTRY_AUTH=ghcr.io=<user>:<token>. Use this if your login is stored in a credential helper ("credsStore"inconfig.json).
Use tokens with read-only scope (read:packages for GHCR). Containers whose registry rejects the pull show Auth required with a hint.
- Create a Proxy Host pointing to
http://<server-ip>:3000 - SSL tab: request a certificate, enable Force SSL, HTTP/2 and HSTS
- Enable Websockets Support (needed by the container console), Block Common Exploits and, ideally, an Access List (IP allow-list or basic auth)
- In
.envaddTRUST_PROXY=<npm-ip>andCOOKIE_SECURE=true, then recreate the container - Do not forward port
3000on your router, and do not add CORS headers in NPM
See the full hardening checklist.
-
From the app: Update on the DockerUpdates row (or Update all). A helper container recreates it with the new image and the page reloads automatically.
-
Manually:
docker pull ghcr.io/pixlgalaxy/dockerupdates:latest docker rm -f dockerupdates # run the same `docker run` command again
Requirements: Node.js 22.9+ and a running Docker daemon.
# Backend (http://localhost:3000)
cd backend
cp .env.example .env # set a strong ADMIN_PASSWORD
npm install
npm run dev
# Frontend (http://localhost:5173, proxies /api to the backend)
cd frontend
npm install
npm run devIf you add npm packages on Windows or macOS, regenerate the lockfile on Linux before committing. npm leaves out optional dependencies of other platforms, and npm ci in the Docker build then fails with "Missing: ... from lock file":
docker run --rm -v "$PWD/frontend:/src" -w /src node:26-alpine npm install --package-lock-only --ignore-scriptsBuild the image locally:
docker build --build-arg APP_VERSION=dev -t dockerupdates .Stack: React 19 + TypeScript + Vite + Tailwind CSS 4 (frontend), Node.js + Express 5 + dockerode (backend). CI builds multi-arch images (linux/amd64, linux/arm64) and publishes them to GHCR; Dependabot keeps actions, npm packages and the base image updated.
DockerUpdates has full control over Docker on the host: treat access to it like root access. Read SECURITY.md for the security model, built-in protections and how to report a vulnerability privately.
MIT © 2026 PixlGalaxy
You can use, modify and redistribute DockerUpdates freely, as long as the copyright notice (the DockerUpdates name and its authors) and the license text are kept.











