Docker Compose
Docker Compose runs Long Tail with everything it talks to: Postgres, S3-compatible storage (MinIO) and, in the boilerplate, a NATS event bus. At the end of this page you have the dashboard, the REST API and /mcp running on your machine against the same services a cloud deployment uses.
There are two stacks:
| Stack | Who it is for | Dashboard |
|---|---|---|
long-tail-boilerplate |
App teams building workflows on the published package | http://localhost:3030 |
long-tail |
Contributors changing Long Tail itself | http://localhost:3000 |
Prerequisites
Section titled “Prerequisites”- Docker with Docker Compose
- Node 22 or later (for
npm installand the test scripts) - Git
Boilerplate stack
Section titled “Boilerplate stack”-
Clone the boilerplate and create your
.env:Terminal window git clone https://github.com/hotmeshio/long-tail-boilerplate.gitcd long-tail-boilerplatecp .env.example .envnpm install -
Set the superadmin password for the first boot. The seed creates the
superadminaccount only whenSEED_ADMIN_PASSWORDis set and no such user exists yet:.env SEED_ADMIN_PASSWORD=your-password -
Start the stack:
Terminal window docker compose up -d --build -
Open
http://localhost:3030and sign in assuperadminwith the password you set.
Services
Section titled “Services”| Service | Image | Host ports | Purpose |
|---|---|---|---|
app |
Dockerfile, dev stage |
3030 | Dashboard, REST API, /mcp and workers in one process |
postgres |
postgres:16 |
5416 | Workflow state, escalations, users, config |
nats |
nats:2-alpine |
4222 (client), 9222 (WebSocket) | Event bus for live dashboard updates |
minio |
cgr.dev/chainguard/minio |
9002 (API), 9003 (console) | S3-compatible file storage |
The app container mounts src/, scripts/ and tests/. ts-node-dev restarts the process when a file changes.
| URL | What it serves |
|---|---|
http://localhost:3030 |
Dashboard |
http://localhost:3030/api |
REST API |
http://localhost:3030/mcp |
MCP endpoint |
http://localhost:3030/health |
Health check |
http://localhost:9003 |
MinIO console (minioadmin / minioadmin) |
Environment
Section titled “Environment”Compose reads .env and then sets the in-network values on top:
| Variable | Compose value | Purpose |
|---|---|---|
POSTGRES_HOST |
postgres |
Database host inside the network |
POSTGRES_PORT |
5432 |
Database port inside the network |
LT_S3_ENDPOINT |
http://minio:9000 |
Storage endpoint the server calls |
LT_S3_PUBLIC_ENDPOINT |
http://localhost:9002 |
Storage endpoint the browser receives |
NATS_URL |
nats://nats:4222 |
Server-to-NATS connection |
NATS_TOKEN |
dev_api_secret |
NATS auth token |
NATS_WS_TARGET |
ws://nats:9222 |
NATS WebSocket the server proxies for the dashboard |
LT_OAUTH_ISSUER |
http://localhost:3030 |
Turns on OAuth sign-in for MCP clients at /mcp |
SEED_ADMIN_PASSWORD |
from .env |
First-boot superadmin password |
NODE_OPTIONS |
--max-old-space-size=3072 --max-semi-space-size=64 |
Node heap sizing |
The rest of .env holds PORT, JWT_SECRET, the POSTGRES_* credentials, the LT_S3_* storage settings and optional LLM and OAuth keys. .env.example lists every variable with its local default.
Host ports move with PORT, PG_PORT, NATS_PORT, NATS_WS_PORT, MINIO_PORT and MINIO_CONSOLE_PORT.
Connect a SQL client
Section titled “Connect a SQL client”| Field | Value |
|---|---|
| Host | localhost |
| Port | 5416 |
| User | postgres |
| Password | password |
| Database | myapp |
| SSL | Off |
Run the production topology locally
Section titled “Run the production topology locally”docker-compose.multi.yml replaces the single app with one API container and two worker containers, the same split the AWS deployment runs:
docker compose -f docker-compose.yml -f docker-compose.multi.yml up -d --buildEach container sets APP_ROLE (api or worker). See Run modes for what each role starts.
npm test # Unit testsnpm run test:integration # Integration tests against the running stackContributor stack
Section titled “Contributor stack”The long-tail repo runs the package from source, with the example workflows and seed data loaded.
-
Clone and start:
Terminal window git clone https://github.com/hotmeshio/long-tail.gitcd long-taildocker compose up -d --build -
Open
http://localhost:3000. The example workflows seed the dashboard. Sign in assuperadminwith the password declared underseed.admininindex.ts.
On first boot the dev entrypoint installs the dashboard’s dependencies and builds it when dashboard/dist is missing.
Services
Section titled “Services”| Service | Host ports | Purpose |
|---|---|---|
long-tail |
3000 (API and dashboard), 9230 (Node debugger) | Server and workers, run with ts-node-dev |
postgres |
5415 | Database, tuned for write-heavy workloads |
minio |
9000 (API), 9001 (console) | S3-compatible file storage |
mock-oauth |
9080 | Test OAuth provider for the sign-in flows |
Change a host port with LT_PORT, LT_DEBUG_PORT, LT_PG_PORT, LT_MINIO_PORT, LT_MINIO_CONSOLE_PORT or LT_MOCK_OAUTH_PORT.
The long-tail service sets LT_SEED_SERVICE_KEYS=true, which prints the seeded mcp-service account’s API keys to the container log on first start. JWT_SECRET, LT_OAUTH_ISSUER, the LLM keys and the Honeycomb keys pass through from your shell or .env.
Overrides
Section titled “Overrides”Layer an override file to add a service:
| File | Adds | Command |
|---|---|---|
docker-compose.nats.yml |
NATS for cross-container events and the dashboard WebSocket | docker compose -f docker-compose.yml -f docker-compose.nats.yml up -d --build |
docker-compose.external.yml |
An external MCP server that authenticates with a service token | docker compose -f docker-compose.yml -f docker-compose.external.yml up |
docker-compose.machines.yml |
An MQTT machine broker, a site NATS and a mock line (layer it on the NATS override) | docker compose -f docker-compose.yml -f docker-compose.nats.yml -f docker-compose.machines.yml up -d --build |
With the NATS override, EVENT_TRANSPORT=nats replaces Socket.IO and the dashboard receives events over the NATS WebSocket on port 9222.
Full reset
Section titled “Full reset”-v deletes the named Postgres and MinIO volumes. Everything starts from an empty database:
docker compose down -vdocker compose up -d --builddocker compose exec app npm run seeddocker compose down -vdocker compose up -d --buildAfter a dependency bump
Section titled “After a dependency bump”The contributor stack mounts anonymous volumes at /app/node_modules and /app/dashboard/node_modules. Compose reuses them across up --build, so the container keeps the old packages after you change package.json. Renew the anonymous volumes:
docker compose up -d --build -V-V (--renew-anon-volumes) replaces only anonymous volumes. The named pgdata and miniodata volumes, and your data, stay.
