> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bronto.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Docker build traces with BuildKit and OpenTelemetry

> Send Docker BuildKit build traces to Bronto over OTLP to see per-step durations, cache hits and misses, and where build time is spent.

BuildKit — the builder behind `docker build` and `docker buildx` — is already instrumented with OpenTelemetry. It records a trace for every build with one span per Dockerfile step, and exports straight to Bronto over OTLP/HTTP, so no Collector is involved. To collect runtime logs from your running containers instead, see [Docker](./docker).

## Prerequisites

* A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key))
* Docker Engine with Buildx (verified with Docker 29.6, Buildx v0.35, BuildKit v0.31)
* A builder on the `docker-container` driver — the default `docker` driver runs BuildKit inside the Docker daemon, where these variables cannot be set

## See the trace locally

BuildKit keeps a record of recent builds, so you can view a trace before configuring anything:

```bash theme={"dark"}
docker buildx history trace
```

These records are local and short-lived. Exporting to Bronto turns them into build history you can query across every developer machine and CI runner.

## Configure the builder

```bash theme={"dark"}
export OTEL_SERVICE_NAME=<YOUR_DATASET_NAME>

docker buildx create --name otel-builder --use \
  --driver docker-container \
  --driver-opt env.OTEL_TRACES_EXPORTER=otlp \
  --driver-opt env.OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \
  --driver-opt env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://ingestion.<REGION>.bronto.io/v1/traces \
  --driver-opt env.OTEL_EXPORTER_OTLP_HEADERS=x-bronto-api-key=<YOUR_API_KEY> \
  --driver-opt env.OTEL_SERVICE_NAME=<YOUR_DATASET_NAME>

docker buildx inspect --bootstrap
```

Set `<REGION>` to `eu` or `us`. `service.name` selects the dataset. From here, every `docker buildx build` sends its trace to Bronto.

Use `docker buildx build` rather than `docker build`. On Docker Desktop, `docker build` runs on the built-in `docker` driver regardless of the builder selected with `--use`, so it will not be instrumented.

Export `OTEL_SERVICE_NAME` in your shell as well as on the builder. A build emits spans from two processes: BuildKit emits the steps, and the `buildx` CLI emits the root `build` span. Without the shell export the CLI reports `service.name=buildx`, putting the root span in a different dataset from its own steps.

## What you will see in Bronto

Open [Tracing](https://app.bronto.io/tracing) and filter by your service name — build traces appear under Tracing, not log search. Span names are the Dockerfile steps verbatim, such as `[4/4] RUN npm ci` and `exporting to image`. A step that ran appears under its own name; a step served from cache appears as `load cache: <step>`, emitted for the deepest still-valid step, so it identifies exactly where the cache broke.

Grouping spans by name and summing `$span.duration_nano` shows where build time actually goes, and counting `load cache:` spans shows which step invalidates most often.

<img src="https://mintcdn.com/bronto/l0cf9IFBkSTnxgjF/images/integrations/assets/images/docker-build-dashboard.png?fit=max&auto=format&n=l0cf9IFBkSTnxgjF&q=85&s=2da9523e7b5e0c481c2461c2206890c6" alt="Bronto dashboard showing image export cost by project, total time per build step, where the cache breaks, and average build time by project" width="1568" height="644" data-path="images/integrations/assets/images/docker-build-dashboard.png" />

## Troubleshooting

* **No traces?** Use `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` with the full `/v1/traces` path. The base `OTEL_EXPORTER_OTLP_ENDPOINT` variable appends `/v1/{signal}`, producing `/v1/traces/v1/traces`, and the export then fails silently. Also confirm `OTEL_EXPORTER_OTLP_HEADERS` is set on the builder.
* **Trace has no root span?** `OTEL_SERVICE_NAME` is not exported in the shell running the build.
* **Slow first build?** A new `docker-container` builder starts with an empty cache.
* In CI, [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) sets its own `OTEL_*` variables, which can conflict with these.

***

For assistance or questions, contact [support@bronto.io](mailto:support@bronto.io).
