mirror of
https://github.com/docker/docs.git
synced 2026-03-27 14:28:47 +07:00
Merge pull request #19776 from dvdksn/initial-otel-support
cli: document initial otel support and usage
This commit is contained in:
@@ -54,6 +54,7 @@ GeoNetwork
|
||||
Git
|
||||
GitHub( Actions)?
|
||||
Google
|
||||
Grafana
|
||||
HTTP
|
||||
HyperKit
|
||||
IPs?
|
||||
@@ -77,6 +78,7 @@ Nginx
|
||||
Nuxeo
|
||||
OAuth
|
||||
OCI
|
||||
OTel
|
||||
Okta
|
||||
Postgres
|
||||
PowerShell
|
||||
|
||||
164
content/config/otel.md
Normal file
164
content/config/otel.md
Normal file
@@ -0,0 +1,164 @@
|
||||
---
|
||||
title: OpenTelemetry for the Docker CLI
|
||||
description: Learn about how to capture OpenTelemetry metrics for the Docker command line
|
||||
keywords: otel, opentelemetry, telemetry, traces, tracing, metrics, logs
|
||||
---
|
||||
|
||||
{{< introduced engine 26.1.0 >}}
|
||||
|
||||
The Docker CLI supports [OpenTelemetry](https://opentelemetry.io/docs/) instrumentation
|
||||
for emitting metrics about command invocations. This is disabled by default.
|
||||
You can configure the CLI to start emitting metrics to the endpoint that you
|
||||
specify. This allows you to capture information about your `docker` command
|
||||
invocations for more insight into your Docker usage.
|
||||
|
||||
Exporting metrics is opt-in, and you control where data is being sent by
|
||||
specifying the destination address of the metrics collector.
|
||||
|
||||
## What is OpenTelemetry?
|
||||
|
||||
OpenTelemetry, or OTel for short, is an open observability framework for
|
||||
creating and managing telemetry data, such as traces, metrics, and logs.
|
||||
OpenTelemetry is vendor- and tool-agnostic, meaning that it can be used with a
|
||||
broad variety of Observability backends.
|
||||
|
||||
Support for OpenTelemetry instrumentation in the Docker CLI means that the CLI can emit
|
||||
information about events that take place, using the protocols and conventions
|
||||
defined in the Open Telemetry specification.
|
||||
|
||||
## How it works
|
||||
|
||||
The Docker CLI doesn't emit telemetry data by default. Only if you've set an
|
||||
environment variable on your system will Docker CLI attempt to emit OpenTelemetry
|
||||
metrics, to the endpoint that you specify.
|
||||
|
||||
```bash
|
||||
DOCKER_CLI_OTEL_EXPORTER_OTLP_ENDPOINT=<endpoint>
|
||||
```
|
||||
|
||||
The variable specifies the endpoint of an OpenTelemetry collector, where telemetry data
|
||||
about `docker` CLI invocation should be sent. To capture the data, you'll need
|
||||
an OpenTelemetry collector listening on that endpoint.
|
||||
|
||||
The purpose of a collector is to receive the telemetry data, process it, and
|
||||
exports it to a backend. The backend is where the telemetry data gets stored.
|
||||
You can choose from a number of different backends, such as Prometheus or
|
||||
InfluxDB.
|
||||
|
||||
Some backends provide tools for visualizing the metrics directly.
|
||||
Alternatively, you can also run a dedicated frontend with support for
|
||||
generating more useful graphs, such as Grafana.
|
||||
|
||||
## Setup
|
||||
|
||||
To get started capturing telemetry data for the Docker CLI, you'll need to:
|
||||
|
||||
- Set the `DOCKER_CLI_OTEL_EXPORTER_OTLP_ENDPOINT` environment variable to point to an OpenTelemetry collector endpoint
|
||||
- Run an OpenTelemetry collector that receives the signals from CLI command invocations
|
||||
- Run a backend for storing the data received from the collector
|
||||
|
||||
The following Docker Compose file bootstraps a set of services to get started with OpenTelemetry.
|
||||
It includes an OpenTelemetry collector that the CLI can send metrics to,
|
||||
and a Prometheus backend that scrapes the metrics off the collector.
|
||||
|
||||
```yaml {collapse=true,title=compose.yml}
|
||||
name: cli-otel
|
||||
services:
|
||||
prometheus:
|
||||
image: prom/prometheus
|
||||
command:
|
||||
- "--config.file=/etc/prometheus/prom.yml"
|
||||
ports:
|
||||
# Publish the Prometheus frontend on localhost:9091
|
||||
- 9091:9090
|
||||
restart: always
|
||||
volumes:
|
||||
# Store Prometheus data in a volume:
|
||||
- prom_data:/prometheus
|
||||
# Mount the prom.yml config file
|
||||
- ./prom.yml:/etc/prometheus/prom.yml
|
||||
otelcol:
|
||||
image: otel/opentelemetry-collector
|
||||
restart: always
|
||||
depends_on:
|
||||
- prometheus
|
||||
ports:
|
||||
- 4317:4317
|
||||
volumes:
|
||||
# Mount the otelcol.yml config file
|
||||
- ./otelcol.yml:/etc/otelcol/config.yaml
|
||||
|
||||
volumes:
|
||||
prom_data:
|
||||
```
|
||||
|
||||
This service assumes that the following two configuration files exist alongside
|
||||
`compose.yml`:
|
||||
|
||||
- ```yaml {collapse=true,title=otelcol.yml}
|
||||
# Receive signals over gRPC and HTTP
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
http:
|
||||
|
||||
# Establish an endpoint for Prometheus to scrape from
|
||||
exporters:
|
||||
prometheus:
|
||||
endpoint: "0.0.0.0:8889"
|
||||
|
||||
service:
|
||||
pipelines:
|
||||
metrics:
|
||||
receivers: [otlp]
|
||||
exporters: [prometheus]
|
||||
```
|
||||
|
||||
- ```yaml {collapse=true,title=prom.yml}
|
||||
# Configure Prometheus to scrape the OpenTelemetry collector endpoint
|
||||
scrape_configs:
|
||||
- job_name: "otel-collector"
|
||||
scrape_interval: 1s
|
||||
static_configs:
|
||||
- targets: ["otelcol:8889"]
|
||||
```
|
||||
|
||||
With these files in place:
|
||||
|
||||
1. Start the Docker Compose services:
|
||||
|
||||
```console
|
||||
$ docker compose up
|
||||
```
|
||||
|
||||
2. Configure Docker CLI to export telemetry to the OpenTelemetry collector.
|
||||
|
||||
```console
|
||||
$ export DOCKER_CLI_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
|
||||
```
|
||||
|
||||
3. Run a `docker` command to trigger the CLI into sending a metric signal to
|
||||
the OpenTelemetry collector.
|
||||
|
||||
```console
|
||||
$ docker version
|
||||
```
|
||||
|
||||
4. To view telemetry metrics created by the CLI, open the Prometheus expression
|
||||
browser by going to <http://localhost:9091/graph>.
|
||||
|
||||
5. In the **Query** field, enter `command_time_milliseconds_total`, and execute
|
||||
the query to see the telemetry data.
|
||||
|
||||
## Available metrics
|
||||
|
||||
Docker CLI currently exports a single metric, `command.time`, which measures
|
||||
the execution duration of a command in milliseconds. This metric has the
|
||||
following attributes:
|
||||
|
||||
- `command.name`: the name of the command
|
||||
- `command.status.code`: the exit code of the command
|
||||
- `command.stderr.isatty`: true if stderr is attached to a TTY
|
||||
- `command.stdin.isatty`: true if stdin is attached to a TTY
|
||||
- `command.stdout.isatty`: true if stdout is attached to a TTY
|
||||
@@ -1570,6 +1570,8 @@ Manuals:
|
||||
title: Filter commands
|
||||
- path: /config/formatting/
|
||||
title: Format command and log output
|
||||
- path: /config/otel/
|
||||
title: OpenTelemetry
|
||||
- sectiontitle: Manage resources
|
||||
section:
|
||||
- path: /config/pruning/
|
||||
|
||||
@@ -1,36 +1,41 @@
|
||||
<div class="group relative">
|
||||
<button x-data="{ code: '{{encoding.Base64Encode .Inner}}', copying: false }"
|
||||
class="absolute right-3 top-3 z-20 text-gray-light-300 dark:text-gray-dark-600" title="Copy" @click="window.navigator.clipboard.writeText(atob(code).replaceAll(/^\$\s*/gm, ''));
|
||||
copying = true;
|
||||
setTimeout(() => copying = false, 2000);">
|
||||
<span :class="{ 'group-hover:block' : !copying }" class="icon-svg hidden">{{ partialCached "icon" "content_copy" "content_copy" }}</span>
|
||||
<span :class="{ 'group-hover:block' : copying }" class="icon-svg hidden">{{ partialCached "icon" "check_circle" "check_circle" }}</span>
|
||||
</button>
|
||||
{{ $lang := .Type | default "text" }} {{ $result := transform.Highlight .Inner
|
||||
$lang .Options }}
|
||||
<div class="syntax-light dark:syntax-dark">
|
||||
{{ with .Attributes.collapse }}
|
||||
<div x-data="{ collapse: true }" class="relative scroll-mt-20 overflow-clip"
|
||||
x-init="$watch('collapse', value => $root.scrollIntoView({ behavior: 'smooth'}))">
|
||||
<div x-show="collapse"
|
||||
class="to-transparent absolute z-10 flex h-32 w-full flex-col-reverse items-center overflow-clip bg-gradient-to-t from-background-light to-75% bg-cover pb-4 dark:from-background-dark">
|
||||
<button @click="collapse = false"
|
||||
class="flex items-center rounded-full bg-blue-light px-2 text-sm text-white dark:bg-blue-dark-400">
|
||||
<span>Show more</span>
|
||||
<span class="icon-svg">{{ partialCached "icon" "expand_more" "expand_more" }}</span>
|
||||
</button>
|
||||
<div class="scroll-mt-20" x-data x-ref="root">
|
||||
{{ with .Attributes.title }}
|
||||
<div class="text-sm -mb-3 text-gray-light dark:text-gray-dark">{{ . }}</div>
|
||||
{{ end }}
|
||||
<div class="group relative">
|
||||
<button x-data="{ code: '{{encoding.Base64Encode .Inner}}', copying: false }"
|
||||
class="absolute right-3 top-3 z-20 text-gray-light-300 dark:text-gray-dark-600" title="Copy" @click="window.navigator.clipboard.writeText(atob(code).replaceAll(/^\$\s*/gm, ''));
|
||||
copying = true;
|
||||
setTimeout(() => copying = false, 2000);">
|
||||
<span :class="{ 'group-hover:block' : !copying }" class="icon-svg hidden">{{ partialCached "icon" "content_copy" "content_copy" }}</span>
|
||||
<span :class="{ 'group-hover:block' : copying }" class="icon-svg hidden">{{ partialCached "icon" "check_circle" "check_circle" }}</span>
|
||||
</button>
|
||||
{{ $lang := .Type | default "text" }} {{ $result := transform.Highlight .Inner
|
||||
$lang .Options }}
|
||||
<div class="syntax-light dark:syntax-dark">
|
||||
{{ with .Attributes.collapse }}
|
||||
<div x-data="{ collapse: true }" class="relative overflow-clip"
|
||||
x-init="$watch('collapse', value => $refs.root.scrollIntoView({ behavior: 'smooth'}))">
|
||||
<div x-show="collapse"
|
||||
class="to-transparent absolute z-10 flex h-32 w-full flex-col-reverse items-center overflow-clip bg-gradient-to-t from-background-light to-75% bg-cover pb-4 dark:from-background-dark">
|
||||
<button @click="collapse = false"
|
||||
class="flex items-center rounded-full bg-blue-light px-2 text-sm text-white dark:bg-blue-dark-400">
|
||||
<span>Show more</span>
|
||||
<span class="icon-svg">{{ partialCached "icon" "expand_more" "expand_more" }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div :class="{ 'h-32': collapse }">
|
||||
{{ $result }}
|
||||
<button @click="collapse = true" x-show="!collapse"
|
||||
class="mx-auto -mt-4 flex items-center rounded-b-lg bg-blue-light px-2 text-sm text-white dark:bg-blue-dark-400">
|
||||
<span>Hide</span>
|
||||
<span class="icon-svg">{{ partialCached "icon" "expand_less" "expand_less" }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="{ 'h-32': collapse }">
|
||||
{{ else }}
|
||||
{{ $result }}
|
||||
<button @click="collapse = true" x-show="!collapse"
|
||||
class="mx-auto -mt-4 flex items-center rounded-b-lg bg-blue-light px-2 text-sm text-white dark:bg-blue-dark-400">
|
||||
<span>Hide</span>
|
||||
<span class="icon-svg">{{ partialCached "icon" "expand_less" "expand_less" }}</span>
|
||||
</button>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ else }}
|
||||
{{ $result }}
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user