From c61810543777c117e7064f903e8ebcd9d25128a0 Mon Sep 17 00:00:00 2001 From: Polliog Date: Sat, 4 Jul 2026 15:45:48 +0200 Subject: [PATCH] fix docker container name extraction in fluent bit (#269) --- CHANGELOG.md | 3 +++ docker/extract_container_id.lua | 35 ++++++++++++++++++++++++++++++++- docker/fluent-bit.conf | 2 +- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19381def..bb54ece7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed +- **Docker container logs showed the container ID instead of the name** (#269): the shipped Fluent Bit pipeline had a `Copy container_name service` filter, but nothing ever set `container_name` (the Lua script only extracted the container ID from the log filepath, where the name does not appear), so the copy was a silent no-op and logs reached LogTide with no `service` and only `container_id`/`container_short_id` in metadata. `extract_container_id.lua` now resolves the container name from the container's `config.v2.json` (already available through the existing read-only `/var/lib/docker/containers` mount), caches it per container, and falls back to the 12-char short ID when the file is missing or unreadable, so the `service` field always gets the container name (or at worst the short ID). Verified end-to-end against the real `fluent/fluent-bit` image + ## [1.0.3] - 2026-06-26 A security-focused release. It resolves a batch of privately reported issues (coordinated disclosure via KIberblick.de): cross-tenant read on the dashboard API endpoints, stored XSS via OTLP `service.name` in the service map, an open redirect on the auth-free login/register path, a DNS-rebinding gap in the SSRF guard's HTTP path, a first-admin bootstrap promotion race, and a capability-limit check-then-act race; trace span attributes are now PII-masked as well, and `service.name` is sanitized at ingestion as defense in depth. No database migrations; drop-in upgrade. Alongside the security work: two correctness follow-ups from the multi-engine bug-hunt sweep (issue #255): Sigma detection now honors full SigmaHQ field-modifier chains, and the service-map p95 is a true window percentile on every storage engine. The storage-layer change was validated against real ClickHouse, MongoDB and TimescaleDB. This line also fixes two operational bugs: a Redis memory leak where completed/failed BullMQ jobs were never evicted, and a nightly SigmaHQ sync that re-imported the whole catalog as enabled and auto-created alert rules. Plus a few frontend touch-ups: theme-aware trace/session IDs in the log detail, per-occurrence trace links on the error page, metadata copy buttons, a breadcrumbs timeline and nested metadata columns in log search. diff --git a/docker/extract_container_id.lua b/docker/extract_container_id.lua index 375832df..1d9362dd 100644 --- a/docker/extract_container_id.lua +++ b/docker/extract_container_id.lua @@ -1,5 +1,34 @@ --- Extract container ID from Docker log filepath +-- Extract container ID and name from Docker log filepath -- Path format: /var/lib/docker/containers/CONTAINER_ID/CONTAINER_ID-json.log +-- The container name is not part of the path, so it is read from the +-- config.v2.json file that Docker keeps next to the log file. + +-- Cache of container_id -> container name (or false when not resolvable), +-- so config.v2.json is read once per container, not once per record. +local name_cache = {} + +local function lookup_container_name(container_id) + local cached = name_cache[container_id] + if cached ~= nil then + return cached or nil + end + + local name = nil + local path = "/var/lib/docker/containers/" .. container_id .. "/config.v2.json" + local file = io.open(path, "r") + if file then + local content = file:read("*a") + file:close() + if content then + -- Container names always start with "/" in config.v2.json + -- (volume mounts also have "Name" keys, but without the slash) + name = content:match('"Name"%s*:%s*"/([^"]+)"') + end + end + + name_cache[container_id] = name or false + return name +end function extract_container_id(tag, timestamp, record) -- Get the filepath from the record @@ -15,6 +44,10 @@ function extract_container_id(tag, timestamp, record) record["container_id"] = container_id -- Add short ID (first 12 chars, like docker ps shows) record["container_short_id"] = container_id:sub(1, 12) + -- Resolve the container name; fall back to the short ID so the + -- downstream "Copy container_name service" filter always works + record["container_name"] = lookup_container_name(container_id) + or record["container_short_id"] end end diff --git a/docker/fluent-bit.conf b/docker/fluent-bit.conf index 98c0eab6..5ed3ae98 100644 --- a/docker/fluent-bit.conf +++ b/docker/fluent-bit.conf @@ -61,7 +61,7 @@ Reserve_Data On Preserve_Key On -# Extract container ID from filepath using Lua +# Extract container ID from filepath and container name from config.v2.json using Lua [FILTER] Name lua Match docker.*