User guide
Everything about DockBeacon — from first install to multi-host log merges, compose stacks, and power-user shortcuts. Written for v0.7.0.
Getting started
DockBeacon is a self-hosted web app that replaces juggling SSH sessions and docker logs commands. Install the package, open http://<host>:9447, sign in, pick containers, and stream. That HTTP URL is the supported zero-config path for lab and staging. Production puts TLS on a reverse proxy in front of the same port.
-
Install the package
Debian/Ubuntu or RHEL/Fedora — see the install page.
Fastest: the one-step installer installs, asks standalone or agent, and starts the service.
curl -fsSL https://dock-beacon.web.app/install.sh -o install.sh sudo bash install.sh
Or add the repo yourself:curl -fsSL https://govindsingh9447.github.io/docker-log-viewer-packages/install-apt.sh -o install-apt.sh less install-apt.sh sudo bash install-apt.sh sudo apt-get install docker-log-viewer
-
Configure the service
Edit
/etc/docker-log-viewer/docker-log-viewer.env, then enable systemd.sudo nano /etc/docker-log-viewer/docker-log-viewer.env # APP_MODE=standalone # SERVER_NAME=my-host # PROJECTS_DIR=/home/ubuntu/projects # PORT=9447 # LISTEN_ADDR=0.0.0.0 sudo systemctl enable --now docker-log-viewer
-
Open the UI & sign in
Browse to
http://<host>:9447. No TLS setup is required for lower environments. On first boot, a temporary password is printed injournalctl -u docker-log-viewerif you did not setAUTH_PASS. The login screen and header show the installed app version (for example v0.2.0) so you can confirm upgrades at a glance. - Select containers → View logs Check one or more containers in the left sidebar, then click View logs. Press Start live to tail in real time.
APP_MODE=standalone serves the full UI + API (your control plane).
APP_MODE=agent is API-only on worker hosts — add agents in Settings → Servers. Sign in once on the control plane; agents that share AUTH_SECRET do not ask again.
UI tour
The interface has three main areas: header (server switch, health, role), sidebar (containers or stacks), and the main panel (logs or stack editor).
PROJECTS_DIR.sudo apt-get install --only-upgrade docker-log-viewer or sudo dnf upgrade docker-log-viewer), then hard-refresh the browser.
Version comes from the binary (GET /api/info) — a stale install can report an old package while still serving an older UI.
Viewing logs
Step 1 — Pick containers
Use the search box to filter by name, ID, or image. Enable Include stopped to see exited containers. Selected count appears above the list.
Step 2 — View logs
Click View logs (or press Enter when containers are checked). The header shows merged container names as chips — click a chip to mute that container’s lines in the stream.
Step 3 — Live vs fetch
- Start live — WebSocket tail; reconnects automatically on drop.
- Pause — freeze the stream without disconnecting (buffer keeps filling; resume to catch up).
- Fetch — one-shot pull using tail size and time range (Last 15m / 1h / 6h / 24h / custom since-until).
Step 4 — Timestamps & auto-scroll
Toggle Timestamps to prefix each line. Auto-scroll keeps you at the bottom; when you scroll up, a ↓ New lines button appears.
Copy & download
Use Copy for the currently visible buffer, or Download to save a text file. Both respect active filters (muted containers and text/level filters).
Inspect & restart
Inspect opens a drawer with container details. Inspect, Start, Stop, and Restart are visible only to operator and admin roles.
Filter & search
The filter box above the log output searches displayed lines. Press / anywhere (outside inputs) to focus it.
Plain text
Type any substring — matching text is highlighted in amber. Works on the full rendered line including container tags.
Regex mode (.* button)
Click the .* chip to treat the filter as a JavaScript regular expression. Invalid patterns show a toast and fall back safely. Regex preference is saved and included in share URLs (?regex=1).
Log level filter
The level dropdown filters by severity: Errors only, Warnings+, or Info+. Useful when a noisy service floods info lines but you need the failures.
Clickable tokens
UUIDs, container IDs, and IP addresses in log text are underlined — click to insert them into the filter instantly.
JSON highlighting
Structured JSON in log lines is detected automatically (brace-matched; Laravel-style [timestamp] prefixes are skipped).
Pretty vs compact
Toggle Pretty JSON in the filter bar:
- On — indented block with syntax colors (keys, strings, numbers, booleans, null).
- Off — inline compact highlighting without extra padding.
Full-window mode
Click Expand in the filter bar (or press e) for a distraction-free view: only the filter strip and log output remain. Header, sidebar, stats, and main toolbar hide.
- Connection status appears as a compact pill in the filter bar (live / paused / error).
- Press Esc or e again to exit.
- All filter controls (regex, JSON, wrap, font, share) stay available.
CPU & memory stats
When live streaming active containers, a stats strip appears below the log header. Each card shows:
- Container name and current CPU % / memory usage
- Mini sparklines for the last ~60 samples (fixed 0–100% scale so graphs stay comparable)
Cards update in place — no duplicate cards when stats refresh. Stats require Docker stats API access on the host.
PM2 logs
On a host that already runs PM2, the Logs sidebar shows a Docker / PM2 switch. Hosts without a PM2 daemon stay Docker-only. Stacks stays Docker Compose. DockBeacon does not start a PM2 daemon.
- The list shows name, status, restarts, uptime, and memory.
- Stream Out, Err, or Both. Lines are prefixed
[app] [out]or[app] [err]. - Live, pause, fetch, filter, wrap, tail, and time range work the same as container logs.
- Operators and admins can start, stop, or restart an app that is already in the list. Viewers cannot. The action asks for confirmation in the page, not a browser dialog.
The service keeps running as docker-log-viewer. Grant it read access to the PM2 log files once, as root:
sudo apt-get install acl sudo /usr/lib/docker-log-viewer/pm2-grant-access sudo systemctl restart docker-log-viewer
That sets an ACL on the PM2 log directory and installs a narrow sudo rule. App status uses pm2 jlist. Start, stop, and restart use pm2-ctl, which only runs those three commands for an app from the last list. Re-run the grant command if PM2 is installed after DockBeacon.
Alerts
The control plane checks itself and every agent every 30 seconds. The Alerts button in the header shows how many alerts are new; open it to see what is active (new ones are tagged New) and recent history. Everyone can see alerts. Admins set them up in Settings → Alerts.
| Rule | Fires when |
|---|---|
| Container unhealthy | Its health check is failing. |
| Container exited | It stopped unexpectedly (a non-zero exit code; a normal docker stop does not count). The message explains common codes, such as 137 (killed, often out of memory). |
| Restart loop | It crashed several times in a short window (default 3 in 10 minutes). |
| Container memory | It is near its memory limit. |
| PM2 app errored | PM2 gave up restarting the app. |
| PM2 restart loop | The app restarted several times in a short window. Manual restarts count too. |
| Host CPU / memory / disk | The server stays above the threshold you set. |
| Docker down | DockBeacon cannot reach the Docker Engine. |
| Agent offline | An agent stops answering. |
- Channels: Slack, Microsoft Teams, Discord (incoming webhooks), or a generic JSON webhook. Use Test to send a sample. Slack and Discord can mention
@hereor@channel. - Each rule can wait a few minutes before firing, so short blips stay quiet. Optionally send a Resolved message when it clears.
- Ignore lists containers or apps that should never alert, such as one-off jobs.
- Set DockBeacon address to your public URL so messages link back to the right page.
Webhook URLs are kept on the server and never shown again after you save them. See Security → Alerts and webhooks.
Timeline & Diagnose
Timeline answers "what changed?". For a container or a whole stack it lists starts, stops, crashes, health changes, and who restarted, redeployed, or edited what. Docker events are recorded continuously and kept 14 days.
Diagnose answers "why is it unhealthy?". It reads the health check log, exit code, restart history, memory, recent error lines, sibling containers in the same stack, and host disk, then explains the likely cause in plain words. It is read-only and never shows env values, so viewers can use it too.
Multi-host & groups
Architecture
Standalone (control plane)
APP_MODE=standalone on one host. Serves UI + API. This is where you browse containers and stacks locally.
Agent (worker)
APP_MODE=agent on other hosts. API only — no browser UI. Set CORS_ORIGINS to your control plane URL.
Add remote servers
- Open Settings (header) → Servers section.
- Add display name + URL e.g.
http://10.0.1.5:9447, modeagent. - Switch hosts from the header. You stay signed in. The agent accepts the control-plane session when
AUTH_SECRETis the same on both hosts. Use Test on the server row to check the connection. - Use the header dropdown to switch between standalone and agents.
Host groups
When adding a server, set an optional Group (e.g. Production). Servers with the same group name appear as a single merged entry in the server list. Selecting a group streams logs from all hosts in that group into one view — ideal when the same service runs on multiple machines.
Stacks mode
Switch the sidebar to Stacks to manage Docker Compose projects discovered under PROJECTS_DIR on the server. Requires operator or admin role for edits.
Tabs
| Tab | Purpose |
|---|---|
| Compose YAML | Edit docker-compose.yml (or project compose file). Save creates a backup first; Diff shows changes before write. |
| Env | Edit .env. Secrets may be masked — toggle Reveal secrets to show values. |
| Images | List local images, set IMAGE_NAME, pull new tags, then Compose up. |
| Config | Edit allowlisted host files (nginx configs, etc.) configured on the server. |
Lifecycle buttons
After selecting a project: Start, Stop, Restart, or Compose up. Status syncs in the header. Restore from timestamped backups via the backups dropdown.
Save shortcut in stack editor: Ctrl+S / ⌘+S.
Settings & RBAC
Open Settings from the header.
Password
Any signed-in user can change their own password (min 8 characters).
Roles
| Role | Can do |
|---|---|
viewer | Read Docker and PM2 logs, switch servers. Cannot inspect containers, or start, stop, or restart containers and PM2 apps, and cannot open Settings → Servers. |
operator | Everything viewer + restart containers, start / stop / restart PM2 apps, edit stacks, compose lifecycle, manage servers |
admin | Everything operator + manage users and roles |
User management (admin only)
Create users with username, password, and role. Users are stored in the server’s users file (seeded from AUTH_USER / AUTH_PASS on first boot).
Security
Treat DockBeacon as a host admin console. Operator and admin roles can restart containers and edit Compose / .env files — not just read logs. Full details on the security page.
What is implemented
| Area | Behavior |
|---|---|
| Access | HTTP via LISTEN_ADDR + PORT (lab: 0.0.0.0:9447). Production: LISTEN_ADDR=127.0.0.1 + reverse-proxy HTTPS. |
| Login | Local bcrypt users and/or OIDC (OIDC_*). Login rate-limited per IP. AUTH_LOCAL=false disables passwords. |
| Session | HMAC cookie, HttpOnly, SameSite=Lax, COOKIE_SECURE=auto. Also X-Auth-Token / Bearer / Basic. |
| CSRF | Double-submit cookie dlv_csrf + header X-CSRF-Token on mutating cookie-auth requests. |
| RBAC | viewer / operator / admin. Container inspect is operator and admin only. |
| Audit | JSON lines to journal + AUDIT_LOG_PATH. Admins: GET /api/audit. |
| Agents | One control-plane login. Set the same AUTH_SECRET on the standalone UI and every agent. CORS_ORIGINS required (fail closed). WebSocket Origin checked. |
| Service user | systemd User=docker-log-viewer, SupplementaryGroups=docker. Data under /var/lib/docker-log-viewer/. |
| Docker | Standard Docker client env / socket. Optional docker-socket-proxy for blast-radius reduction. |
| Packages | GPG-signed apt/yum when CI has signing key; SHA256SUMS always published. |
Still out of scope
- In-process TLS — HTTPS stays on Nginx / ALB
- SAML (use OIDC IdPs such as Keycloak / Authentik / Google)
http://<host>:9447 is for trusted networks (lab, staging, VPN). On production, set LISTEN_ADDR=127.0.0.1, put TLS in front, restrict agents to the control-plane network, and grant operator only to people you would give Docker socket access.
Production deployment
The process always speaks HTTP on :9447. That is intentional: zero-config for lower environments, HTTPS as a reverse-proxy concern in production.
Production layout: Internet → Nginx/ALB (TLS) → standalone control plane on 127.0.0.1:9447 → agents on private Docker hosts.
# /etc/nginx/sites-available/docker-log-viewer
server {
listen 443 ssl http2;
server_name logs.example.com;
# ssl_certificate /etc/letsencrypt/live/logs.example.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/logs.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:9447;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}
}
If this hostname already serves another application at /, give DockBeacon its own prefix. Set BASE_PATH=/dockbeacon and proxy the prefix through unchanged:
location /dockbeacon/ {
proxy_pass http://127.0.0.1:9447;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}
- systemd —
sudo systemctl enable --now docker-log-viewer. Keep config in/etc/docker-log-viewer/docker-log-viewer.env. - Firewall — allow 443 to the proxy. Allow control plane → agent :9447. Deny 9447 from untrusted networks.
- Agents —
APP_MODE=agent, the sameAUTH_SECRETas the control plane,CORS_ORIGINS=https://logs.example.com,UI_URL=https://logs.example.com. - Health —
GET /health(Docker ping). Back up the users file. - Upgrades — see Upgrade (env file is kept; answer N if apt asks about it). Roll back from the package pool.
Keyboard shortcuts
Shortcuts work when logged in and not typing in an input (except / which always focuses the filter).
| Key | Action |
|---|---|
| / | Focus log filter |
| Enter | View logs (when containers selected) |
| l | Toggle live stream |
| p | Pause / resume |
| f | Fetch logs |
| c | Clear log output |
| e | Toggle full-window expand |
| Esc | Exit expand / close modals / blur input |
| Ctrl+S | Save stack file (Stacks mode) |
Configuration reference
Main environment file: /etc/docker-log-viewer/docker-log-viewer.env
| Variable | Description |
|---|---|
PORT | HTTP listen port (default 9447). Lab/staging: http://<host>:9447. Production: reverse-proxy HTTPS to this port. |
BASE_PATH | Optional prefix such as /dockbeacon when another app already uses /. Empty serves the UI at /. |
LISTEN_ADDR | Bind address. Lab default 0.0.0.0; production prefer 127.0.0.1 behind a reverse proxy. |
APP_MODE | standalone (UI + API) or agent (API only). |
SERVER_NAME | Display name in UI and logs. |
COOKIE_SECURE | auto (default), true, or false for the session cookie Secure flag. |
PROJECTS_DIR | Root directory for compose projects (Stacks mode). |
EXTRA_CONFIG_DIRS | Optional allowlisted host dirs for the Stacks Config tab (e.g. nginx sites). |
AUTH_USER / AUTH_PASS | Seed admin on first boot only. |
AUTH_LOCAL | Set false to disable password login (OIDC-only). |
USERS_FILE | Path to local users JSON (default under /var/lib/docker-log-viewer/). |
AUDIT_LOG_PATH | Optional audit log file path; admins can also use GET /api/audit. |
OIDC_* | Optional SSO: OIDC_ISSUER, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, OIDC_REDIRECT_URL, OIDC_ROLES_CLAIM. |
AUTH_SECRET | HMAC secret for session cookies. Set the same value on the control plane and every agent so one login covers all hosts. |
PM2_HOME / PM2_USER / PM2_BIN | Optional. Leave unset to detect a running PM2 daemon. DockBeacon does not start PM2. |
CORS_ORIGINS | Allowed control-plane origins (required on agents; fail-closed when unset). |
UI_URL | Redirect target when hitting an agent root in the browser. |
ALERTS_FILE | Optional path for alert settings (default alerts.json next to the users file). Set alerts up in Settings, not here. |
EVENTS_RETENTION_DAYS | How long the timeline keeps container events (default 14). |
EVENTS_COLLECTOR | Set off to stop recording container events. |
EVENTS_LOG_PATH | Optional path for the event log (default events.log next to the audit log). |
Installed paths
/usr/bin/docker-log-viewer— binary/usr/share/docker-log-viewer/index.html— UI (standalone)/lib/systemd/system/docker-log-viewer.service— systemd unit
Troubleshooting
Cannot sign in
Check sudo journalctl -u docker-log-viewer -n 50 for the bootstrap password. Verify USERS_FILE permissions if you customized auth.
Live stream disconnects
The UI auto-reconnects. If it loops, check reverse-proxy WebSocket support or firewall rules on port 9447.
Agent not listed / CORS errors
On the agent host set CORS_ORIGINS=http://your-control-host:9447 and the same AUTH_SECRET as the control plane, then restart. Add the agent URL in Settings with mode agent and use Test.
PM2 switch is missing
The Docker / PM2 switch appears only when this host already has a live PM2 daemon. DockBeacon does not start one. Install acl, then run sudo /usr/lib/docker-log-viewer/pm2-grant-access and restart the service.
Stacks empty
Ensure PROJECTS_DIR points to a directory containing compose projects and restart the service.
OIDC login fails
Confirm OIDC_REDIRECT_URL matches the IdP callback exactly (including https). Check journal for OIDC errors after restart.
Stats missing
Stats need running containers and Docker stats access. Stopped containers show no sparklines.