---
title: "Docker Compose"
description: "Production deployment with ClickHouse, PostgreSQL, and OTEL Collector"
---

The root `docker-compose.yml` starts the full LangSight production stack.

## Services

| Service | Port | Purpose |
|---------|------|---------|
| `clickhouse` | 127.0.0.1:8123 (localhost only) | Time-series span storage + reliability analytics |
| `postgres` | 127.0.0.1:5432 (localhost only) | App state: configs, users, alert rules, model pricing |
| `otel-collector` | 4317, 4318 | Receives OTLP traces from agent frameworks |
| `api` | 8000 | LangSight REST API |
| `dashboard` | 3003 (maps to 3002 internal) | Next.js dashboard |

<Warning>
  Database ports (5432, 8123) are not exposed to the host by default. Access databases through the `api` service only. Do not override this in production.
</Warning>

## Start the stack

```bash
# Clone the repo
git clone https://github.com/LangSight/langsight
cd langsight

# Copy and fill in the required secrets
cp .env.example .env
```

Edit `.env` — all of these are required. The stack will fail fast if any are unset:

```bash
# .env

# Admin bootstrap (consumed once on first run)
LANGSIGHT_ADMIN_EMAIL=you@example.com
LANGSIGHT_ADMIN_PASSWORD=your-secure-admin-password

# JWT signing secret (min 32 characters, generate with: openssl rand -hex 32)
AUTH_SECRET=replace-with-32-char-random-string

# PostgreSQL
POSTGRES_PASSWORD=your-secure-postgres-password

# ClickHouse
CLICKHOUSE_USER=langsight
CLICKHOUSE_PASSWORD=your-secure-clickhouse-password
```

```bash
# Start everything
docker compose up -d

# Apply database migrations
docker compose exec api uv run alembic upgrade head

# Check status
docker compose ps
```

<Note>
  On first run, LangSight creates the admin user (from `LANGSIGHT_ADMIN_EMAIL` / `LANGSIGHT_ADMIN_PASSWORD`) and a "Default" project automatically. You can log in at `http://localhost:8000` immediately after migrations complete.
</Note>

## Send your first span

```bash
curl -X POST http://localhost:8000/api/traces/spans \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '[{
    "server_name": "my-mcp",
    "tool_name": "query",
    "started_at": "2026-03-17T12:00:00Z",
    "ended_at": "2026-03-17T12:00:00.042Z",
    "latency_ms": 42.0,
    "status": "success",
    "project_id": "default"
  }]'
```

## Connect your OTEL exporter

```bash
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
```

## Health and readiness probes

| Endpoint | Purpose |
|----------|---------|
| `GET /api/liveness` | Instant liveness probe — returns `{"status": "ok"}` with no I/O |
| `GET /api/readiness` | Readiness probe — checks storage connectivity before returning `200` |

Use `/api/liveness` for container restart checks and `/api/readiness` for load balancer routing.

## Upgrade

```bash
docker compose pull
docker compose up -d
docker compose exec api uv run alembic upgrade head
```

## Volumes

Data persists in named Docker volumes:

| Volume | Contains |
|--------|---------|
| `clickhouse_data` | All span data, health history, reliability aggregations |
| `postgres_data` | Users, projects, server configs, alert rules, model pricing |

## Environment variables reference

| Variable | Required | Description |
|----------|----------|-------------|
| `LANGSIGHT_ADMIN_EMAIL` | Yes (first run) | Bootstrap admin email |
| `LANGSIGHT_ADMIN_PASSWORD` | Yes (first run) | Bootstrap admin password |
| `AUTH_SECRET` | Yes | JWT signing secret |
| `POSTGRES_PASSWORD` | Yes | PostgreSQL password |
| `CLICKHOUSE_USER` | Yes | ClickHouse username |
| `CLICKHOUSE_PASSWORD` | Yes | ClickHouse password |
| `LANGSIGHT_LOG_LEVEL` | No | Log verbosity (default: `INFO`) |
| `LANGSIGHT_REDACT_PAYLOADS` | No | Set `true` to omit span payloads |
