Collect the logs of the local Docker containers

- docker.go follows every running container through the Docker API
  (events + logs with follow), resumes after a restart from the last
  position saved in /data/docker-state.json, reads DOCKER_BACKFILL (1h)
  of history for new containers, strips terminal color codes and guesses
  the severity from the line (JSON, logfmt, [ERROR], ERROR ...).
- Logs carry source_type=docker, container, container_id, image,
  compose_project, compose_service and stream; host is the Docker host.
- Settings > Sources: one switch per container (grouped by compose
  project), enable/disable all, follow new containers automatically.
  Choices are saved per compose service in /data/docker.json.
- Source filter (syslog / docker) in the filter bar and the live view.
- docker-compose: read-only docker-socket-proxy; Logstream and the proxy
  are labelled logstream.exclude=true and never collected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cedricandClaude Opus 5.5 committed 2026-09-28 16:52:05 +02:00
1 parent aad0fb7c16
commit 085095c46f
12 files changed
+974 -10

No files matched your search

+29
View File
@@ -66,6 +66,11 @@
</select>
<select id="host" data-i18n-aria="hostAria"><option value="" data-i18n="allHosts">All hosts</option></select>
<select id="app" data-i18n-aria="appAria"><option value="" data-i18n="allApps">All apps</option></select>
<select id="source" data-i18n-aria="sourceAria">
<option value="" data-i18n="srcAll">All sources</option>
<option value="syslog">Syslog</option>
<option value="docker">Docker</option>
</select>
<span class="spacer"></span>
<span id="count" class="muted"></span>
<div class="export">
@@ -121,6 +126,10 @@
<svg viewBox="0 0 24 24"><path d="M3 12V4a1 1 0 0 1 1-1h8l9 9-9 9z"/><circle cx="8" cy="8" r="1.5"/></svg>
<span data-i18n="tabFilters">Filters</span>
</button>
<button type="button" role="tab" data-tab="sources">
<svg viewBox="0 0 24 24"><path d="M21 8 12 3 3 8v8l9 5 9-5z"/><path d="m3 8 9 5 9-5M12 13v8"/></svg>
<span data-i18n="tabSources">Sources</span>
</button>
<button type="button" role="tab" data-tab="interface">
<svg viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="12" rx="2"/><path d="M8 20h8M12 16v4"/></svg>
<span data-i18n="tabInterface">Interface</span>
@@ -167,6 +176,26 @@
</section>
</div>
<!-- Sources -->
<div class="set-panel" role="tabpanel" data-panel="sources" hidden>
<section class="set-section">
<h3 data-i18n="dockerTitle">Docker containers</h3>
<p id="dockerStatus" class="docker-status"></p>
<div id="dockerBody" hidden>
<label class="switch-row">
<input id="dockerDefault" type="checkbox" class="switch">
<span data-i18n="dockerDefault">Follow new containers automatically</span>
</label>
<div class="docker-actions">
<button id="dockerAll" class="btn" type="button" data-i18n="dockerAll">Enable all</button>
<button id="dockerNone" class="btn ghost" type="button" data-i18n="dockerNone">Disable all</button>
</div>
<div id="dockerList" class="docker-list"></div>
</div>
<p class="muted small" data-i18n="dockerHelp"></p>
</section>
</div>
<!-- Interface -->
<div class="set-panel" role="tabpanel" data-panel="interface" hidden>
<section class="set-section">