Why run a Collector container
Apps can send OTLP straight to Telemtra from inside Docker, but running the OpenTelemetry Collector alongside them gives you batching, retries, and a single egress connection regardless of how many app containers you scale to. The Collector is also where you collect container logs from Docker's JSON file driver and scrape Docker daemon stats — neither of which the app SDK does on its own.
Where this goes in your project
If you already have a docker-compose.yml, you are adding one service and one config file. If you have a Dockerfile for your app, it stays unchanged — the OTel SDK reads its config from environment variables you pass via Compose.
my-service/
├── Dockerfile # your existing app image (unchanged)
├── docker-compose.yml # add the "otelcol" service and OTEL_* env on "app"
├── otel-collector-config.yaml # NEW: the Collector config from the next section
└── .env # TELEMTRA_API_KEY=... 1. Save otel-collector-config.yaml at the same level as docker-compose.yml (the YAML in the next section).
2. Append the otelcol service to your existing docker-compose.yml and add the four OTEL_* environment variables to your existing app service. No code changes needed inside the app if you already use the OpenTelemetry SDK.
3. Put your API key in .env (Compose loads it automatically):
TELEMTRA_API_KEY=tk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 4. Bring everything up:
docker compose up -d The Collector starts first because your app depends on it; the app then exports OTLP to http://otelcol:4318 on the Compose network.
Collector config
Save this as otel-collector-config.yaml next to your docker-compose.yml:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
filelog:
include: [/var/lib/docker/containers/*/*-json.log]
start_at: end
operators:
- type: json_parser
parse_from: body
- type: move
from: attributes.log
to: body
docker_stats:
endpoint: unix:///var/run/docker.sock
collection_interval: 30s
processors:
memory_limiter:
check_interval: 1s
limit_mib: 256
batch:
timeout: 5s
send_batch_size: 1024
exporters:
otlphttp/telemtra:
endpoint: https://ingest.telemtra.io
headers:
x-api-key: ${env:TELEMTRA_API_KEY}
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [otlphttp/telemtra]
metrics:
receivers: [otlp, docker_stats]
processors: [memory_limiter, batch]
exporters: [otlphttp/telemtra]
logs:
receivers: [otlp, filelog]
processors: [memory_limiter, batch]
exporters: [otlphttp/telemtra] docker-compose.yml
services:
otelcol:
image: otel/opentelemetry-collector-contrib:latest
command: ["--config=/etc/otel/config.yaml"]
environment:
- TELEMTRA_API_KEY=${TELEMTRA_API_KEY}
volumes:
- ./otel-collector-config.yaml:/etc/otel/config.yaml:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
- "4317:4317"
- "4318:4318"
restart: unless-stopped
app:
image: your-app:latest
environment:
- OTEL_SERVICE_NAME=checkout-api
- OTEL_RESOURCE_ATTRIBUTES=deployment.environment=production
- OTEL_EXPORTER_OTLP_ENDPOINT=http://otelcol:4318
- OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
depends_on:
- otelcol Run TELEMTRA_API_KEY=your_key docker compose up -d. Your app sends OTLP to the Collector on the internal Compose network; the Collector batches and forwards to Telemtra.
Point your app at the Collector
Inside the Compose network, the Collector is reachable by service name. Set OTEL_EXPORTER_OTLP_ENDPOINT=http://otelcol:4318 in the app container. For OTLP gRPC, use http://otelcol:4317.
Container logs
The filelog receiver reads Docker's JSON log driver output from /var/lib/docker/containers/*/*-json.log. The json_parser operator parses each line, then we move log into the body. Container name and image come from Docker's per-container metadata; you can add a resource processor to enrich.
Docker daemon metrics
The docker_stats receiver talks to the Docker socket and emits per-container CPU, memory, network, and block IO metrics. In Telemtra you can chart them with the same widgets as OTLP-native metrics.
Troubleshooting
- filelog reads nothing. Confirm Docker is using the
json-filelog driver, notjournaldorlocal.docker info | grep "Logging Driver". - docker_stats permission denied. The Collector container needs the Docker socket mounted; mount it read-only as shown above.
- 403 to Telemtra. Confirm
TELEMTRA_API_KEYis set in the host environment when you rundocker compose up. - High memory usage. Lower
limit_mibonmemory_limiterand reducesend_batch_size.
For Kubernetes, see OpenTelemetry on Kubernetes. For protocol details, see What is OTLP? New to Telemtra? The quickstart includes a docker-compose snippet that talks straight to ingest.telemtra.io. Create a workspace to get an API key.