# OTel LGTM (Alpine + supervisord) A single-container observability backend running on Alpine Linux with supervisord. Components: - **Grafana** — visualization UI - **Mimir** — metrics storage - **Loki** — log storage - **Tempo** — trace storage - **OpenTelemetry Collector (contrib)** — OTLP receiver and router ## Ports | Port | Service | Description | |------|---------|-------------| | 3000 | Grafana | Web UI | | 4318 | OTel Collector | OTLP/HTTP endpoint | Only these two ports are exposed. All other services communicate internally on `127.0.0.1`. ## Build ```bash docker build -t otel-lgtm . ``` > The Dockerfile uses BuildKit cache mounts for `apk`. Make sure BuildKit is enabled (default in recent Docker Desktop / `docker buildx`). ### Build args | Build arg | Default | Description | |-----------|---------|-------------| | `ALPINE_VERSION` | `3.24` | Alpine Linux base image version | | `OTELCOL_VERSION` | `0.154.0` | OpenTelemetry Collector Contrib version | Grafana, Mimir, Loki, and Tempo versions are determined by the chosen Alpine repository. Example: ```bash docker build --build-arg OTELCOL_VERSION=0.155.0 -t otel-lgtm . ``` ### Multi-architecture The Dockerfile detects the build architecture at build time, so it works on both `amd64` and `arm64`. To build a true multi-arch image in one command, use Docker BuildKit / `docker buildx`: ```bash docker buildx build --platform linux/amd64,linux/arm64 -t otel-lgtm . ``` ## Run ```bash docker run -p 3000:3000 -p 4318:4318 -v lgtm-data:/data otel-lgtm ``` Grafana is available at http://localhost:3000 with anonymous admin access enabled. Send telemetry to the collector at `http://localhost:4318` (OTLP/HTTP). ## Data persistence All persistent data is written under `/data`: | Path | Service | |------|---------| | `/data/grafana` | Grafana data, logs, and plugins | | `/data/mimir` | Mimir metrics storage | | `/data/loki` | Loki log storage | | `/data/tempo` | Tempo trace storage | Mount a volume there to persist data across container restarts. ## Architecture ``` Application ──OTLP/HTTP──> OTel Collector :4318 │ ├─ metrics ──OTLP/HTTP──> Mimir :9009 ├─ logs ─────OTLP/HTTP──> Loki :3100 └─ traces ───OTLP/HTTP──> Tempo :3200 Grafana :3000 queries Mimir, Loki, and Tempo. ``` ## Read-only root filesystem The image can be run with an immutable root filesystem (`--read-only`). A few runtime-only directories must be mounted as writable `tmpfs`: ```bash docker run --read-only \ -p 3000:3000 -p 4318:4318 \ -v lgtm-data:/data \ --tmpfs /tmp:rw,noexec,nosuid,size=100m \ --tmpfs /run:rw,noexec,nosuid,size=10m \ --tmpfs /var/log/supervisor:rw,noexec,nosuid,size=50m \ otel-lgtm ``` Persistent data continues to live on the `/data` volume, while temporary/runtime state stays in memory. ## Notes - This image is intended for development, demo, and testing environments. - Grafana authentication is disabled (`anonymous` admin). - Grafana’s default async plugin pre-installation is disabled to avoid relying on internet access at startup.