# docker-otel-lgtm runs OpenTelemetry Collector, Prometheus, Tempo, Loki, Pyroscope and Grafana in one Docker image for local development

> grafana/docker-otel-lgtm is a Docker image that bundles the full LGTM observability stack with the OpenTelemetry Collector, pre-wiring all four signal types to their backends with no per-service configuration. The project targets development and demo environments and is not intended for production.

**grafana/docker-otel-lgtm** — An OpenTelemetry backend in a Docker container image

- Repository: https://github.com/grafana/docker-otel-lgtm
- Stars: 2,048 · Forks: 216
- Language: Shell
- License: Apache-2.0
- Published: 2026-10-11 · Updated: 2026-10-11 · Language: en
- Canonical page: https://hysenlabs.com/projects/grafana-docker-otel-lgtm

## docker-otel-lgtm wires the LGTM observability stack together for development without per-backend configuration

Getting OpenTelemetry observability running locally requires the OpenTelemetry Collector, a metrics backend, a trace backend, a log backend, a profiling backend and a visualization tool. Each service needs its own configuration, and the collector needs routing rules to reach each one. docker-otel-lgtm does all of that inside a single Docker image.

The image bundles the OpenTelemetry Collector, Prometheus for metrics, Tempo for traces, Loki for logs, Pyroscope for continuous profiling and Grafana for visualization. All routing is pre-configured inside the image. An instrumented application sends OTLP telemetry to the container and the data appears in Grafana immediately, with no per-backend setup required from the operator.

docker-otel-lgtm is Apache-2.0, v0.35.0 was published on 2026-10-02, and the repository was last pushed on 2026-10-06.

The project targets development, demo and testing environments, not production. The README's callout block directs operators who need a production-ready observability platform with MTTR tooling to Grafana Cloud Application Observability instead.

## The OpenTelemetry Collector fans out each signal type to its backend and can forward to external OTLP endpoints

Inside the container, every telemetry signal passes through the OpenTelemetry Collector before reaching its backend. Metrics go to Prometheus, traces to Tempo, logs to Loki and profiling data to Pyroscope. Grafana connects to all four backends and provides a unified view of traces, metrics, logs and profiling data without any manual datasource setup.

Any application configured with an OTLP exporter can point at the container and send telemetry without touching the collector's routing configuration. The routing from the collector to each backend is fixed inside the image; changing that routing requires building a custom image from the repository.

The collector also handles forwarding to external destinations. Setting `OTEL_EXPORTER_OTLP_ENDPOINT` causes the collector to forward all signals to that endpoint using OTLP/HTTP in addition to routing them to the built-in backends. Per-signal forwarding is also configurable: `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` and `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` route individual signal types to separate destinations. This makes it practical to run docker-otel-lgtm alongside a Grafana Cloud trial or any other OTLP-compatible backend, sending data to both simultaneously.

All five services share the container's process space with a single lifecycle. A resource spike in one backend can affect the others, and a crash in any service takes down the entire container. This is part of why the project is scoped to development and demo work rather than production deployments.

## Pull the image and start it with the included scripts; Apple Container requires additional steps

The Docker image is available on Docker Hub:

```bash
docker pull grafana/otel-lgtm:latest
```

The repository provides platform-specific run scripts that configure required flags and handle runtime detection. Use these instead of `docker run` directly.

On Linux, Unix and macOS with Docker or Podman:

```bash
./run-lgtm.sh
```

On Windows with PowerShell:

```powershell
./run-lgtm
```

The scripts detect the available container runtime automatically: Podman first, then Docker, then Apple Container. Set `CONTAINER_RUNTIME_OVERRIDE` to `docker`, `podman` or `container` to override the detected runtime when multiple runtimes are installed.

Apple Container requires starting the runtime before running the script:

```sh
container system start
CONTAINER_RUNTIME_OVERRIDE=container ./run-lgtm.sh
```

Apple Container defaults to 1G of memory. That allocation is insufficient for the full stack; the run script sets 2G automatically. Workloads that generate significant telemetry volume will need more. Override the limit with `LGTM_CONTAINER_MEMORY`:

```sh
CONTAINER_RUNTIME_OVERRIDE=container LGTM_CONTAINER_MEMORY=4G ./run-lgtm.sh
```

Mise users can run `mise run lgtm` as an alternative, with the mise.toml in the repository root handling the configuration. The build and run scripts also work with mise: `CONTAINER_RUNTIME_OVERRIDE=container mise run lgtm` selects a specific runtime through the same override variable.

## OBI eBPF auto-instrumentation instruments host processes, not only container processes, due to shared PID namespace

OBI (OpenTelemetry eBPF Instrumentation) generates traces and RED metrics for HTTP and gRPC services using eBPF, with no code changes in the target application. Enable it by passing `ENABLE_OBI=true` to the run script:

```sh
ENABLE_OBI=true ./run-lgtm.sh
```

OBI requires a Linux kernel at version 5.8 or later with BTF support. The run scripts add `--pid=host` and `--privileged` Docker flags automatically when OBI is enabled. Running `docker run` directly requires adding those flags manually. OBI is not supported on Apple Container because the `container` CLI does not implement `--privileged` or `--pid=host`.

The `--pid=host` flag's scope extends beyond the container. It shares the host machine's entire PID namespace with the container, so OBI discovers and instruments processes running on the host, not only processes inside the container. The OBI documentation in the README makes this explicit with a concrete example: setting `OBI_TARGET=java` will instrument Java processes running on the host as well as any Java processes the container itself runs. A developer using OBI to trace a single microservice is opting into visibility across all matching processes on the host.

By default, OBI scans ports 80, 443, 8080-8099, 3000-3999 and 5000-5999 for services to monitor. To narrow the scope, set `OBI_TARGET` to a language name (java, python, node, dotnet, ruby) or a regular expression. To restrict monitoring to specific ports, set `OTEL_EBPF_OPEN_PORT`. A targeted invocation for Python services only:

```sh
ENABLE_OBI=true OBI_TARGET=python ./run-lgtm.sh
```

## Per-component debug logging variables control internal output and have no effect on application log collection

The container provides eight environment variables for debug logging of its own internal components. Setting `ENABLE_LOGS_GRAFANA`, `ENABLE_LOGS_LOKI`, `ENABLE_LOGS_PROMETHEUS`, `ENABLE_LOGS_TEMPO`, `ENABLE_LOGS_PYROSCOPE`, `ENABLE_LOGS_OTELCOL` or `ENABLE_LOGS_OBI` turns on verbose output for that specific service. `ENABLE_LOGS_ALL` enables all seven at once and is useful when diagnosing startup failures without knowing which service is responsible.

These variables control only the container's internal component output. They have nothing to do with application log collection, which the OpenTelemetry Collector performs as part of normal operation and routes to Loki independently. Setting `ENABLE_LOGS_LOKI` to debug a Loki connectivity problem does not affect how the collector ingests or processes application logs.

Shutdown behavior is also configurable. The container forwards `SIGTERM` and `SIGINT` to every backend and waits up to five seconds for a graceful stop. Any process still running after that grace period is forcefully stopped. Set `LGTM_SHUTDOWN_TIMEOUT_SECONDS` to adjust the timeout.

All these settings belong in the `.env` file in the repository root or can be passed directly on the command line. The `.env` file approach is cleaner for repeatable development workflows where the same configuration runs across multiple sessions.

## Apple Container, OBI and the single-container model each impose a concrete constraint

Three constraints in the current design matter before committing to docker-otel-lgtm for a development workflow.

First, all five backends run in one container as a single process group. No component is isolated from the others, and there is no option to restart one backend without taking down the entire container. A memory spike in Tempo affects Prometheus's ability to scrape metrics at its normal interval. For a local development tool this is acceptable; for any shared or persistent environment, it is not.

Second, OBI is not available on Apple Container because the `container` CLI does not implement `--privileged` or `--pid=host`. Developers on Apple Silicon who use Apple Container as their container runtime cannot use zero-code eBPF instrumentation and must instrument their applications manually with OTLP exporters. Apple Container's default 1G memory limit also causes the stack to fail with real workloads. The run script sets a 2G default, but `LGTM_CONTAINER_MEMORY` must be set higher for any application that generates non-trivial telemetry volume.

Third, the full OBI kernel requirement (Linux 5.8+ with BTF) excludes developers on macOS or Windows who do not have access to a suitable Linux environment, as well as those on older Linux kernels without BTF support.

The examples directory provides working integrations for dotnet, ebpf-profiler, go, java, nodejs, obi and python, each in its own subdirectory. These are the fastest way to verify that the container works end-to-end with a specific runtime before connecting a real application.

## gcx provides agent-assisted telemetry queries against the local container without a Grafana Cloud account

The repository includes a gcx integration that connects to a locally running docker-otel-lgtm instance and lets developers query application telemetry using agent skills. gcx runs on the host machine and does not require a Grafana Cloud account to function. The setup procedure is in docs/gcx-integration.md.

Operators upgrading from an earlier gcx MCP configuration should review docs/gcx-migration.md before updating. That document covers files removed in the transition and changes to credential handling.

Recent image versions have followed a weekly release pattern. v0.35.0 was published on 2026-10-02, v0.34.0 on 2026-09-25 and v0.33.1 on 2026-09-18. The go.mod file in the repository root declares the module as github.com/grafana/docker-otel-lgtm and targets go 1.25.0. The repository structure includes CONTRIBUTING.md and RELEASING.md alongside the run scripts, making it straightforward to understand how to build from source or contribute an additional language example.

## Conclusion

docker-otel-lgtm is the right tool when a developer needs a full OpenTelemetry backend locally without configuring five separate services. It is the wrong choice for production: all five backends share one container with no component-level isolation, no persistent storage guarantee, and no horizontal scaling. Before using it, verify that OBI's kernel requirement (Linux 5.8+ with BTF) matches your development environment if you plan to use zero-code instrumentation, confirm that Apple Container memory has been raised above 1G with LGTM_CONTAINER_MEMORY if that is your runtime, and check docs/gcx-integration.md for the agent-assisted query setup before attempting any live telemetry investigation.

## FAQ

### Is docker-otel-lgtm suitable for production monitoring?

No. The project explicitly targets development, demo and testing environments. The README links to Grafana Cloud Application Observability for operators who need a production-ready backend with MTTR tooling, durability and high availability.

### Which container runtimes does docker-otel-lgtm support?

Docker, Podman and Apple Container are all supported. The run scripts detect the available runtime automatically in order (Podman, then Docker, then Apple Container) and set the required flags. Set CONTAINER_RUNTIME_OVERRIDE to docker, podman or container to select a specific runtime.

### How do I enable OBI eBPF auto-instrumentation in docker-otel-lgtm?

Pass ENABLE_OBI=true to ./run-lgtm.sh. OBI requires a Linux kernel at version 5.8 or later with BTF support and is not supported on Apple Container. The run scripts add the required --pid=host and --privileged flags automatically.

### Can docker-otel-lgtm forward telemetry to Grafana Cloud or another OTLP endpoint?

Yes. Set OTEL_EXPORTER_OTLP_ENDPOINT to forward all signals to an external endpoint using OTLP/HTTP alongside the built-in backends. Per-signal endpoints OTEL_EXPORTER_OTLP_LOGS_ENDPOINT and OTEL_EXPORTER_OTLP_METRICS_ENDPOINT allow routing individual signal types to separate destinations.

### Why does docker-otel-lgtm run out of memory on Apple Container?

Apple Container defaults to 1G of memory, which is insufficient for the full LGTM stack. The run script sets a 2G default automatically. Set the LGTM_CONTAINER_MEMORY environment variable to a higher value such as 4G for workloads that generate significant telemetry volume.

## Sources

- [grafana/docker-otel-lgtm on GitHub](https://github.com/grafana/docker-otel-lgtm)
- [Issues](https://github.com/grafana/docker-otel-lgtm/issues)
- [License: Apache-2.0](https://github.com/grafana/docker-otel-lgtm/blob/main/LICENSE)
- [README](https://github.com/grafana/docker-otel-lgtm/blob/main/README.md)
- [Releases](https://github.com/grafana/docker-otel-lgtm/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/grafana-docker-otel-lgtm
