Skip to Content

Docker Deployment

Services

The docker-compose.yml runs nine services:

ServiceImagePortPurpose
postgrespostgres:16-alpine5432Relational data (orgs, users, teams, integrations)
clickhouseclickhouse/clickhouse-server:24-alpine8123Telemetry analytics (traces, metrics, logs)
redisredis:7-alpine6379Caching
otel-collectorotel/opentelemetry-collector-contrib4317/4318Telemetry ingestion and routing
backendBuilt from Dockerfile3001NestJS API server
frontendBuilt from Dockerfile3000Next.js dashboard
openmemorymem0/openmemory-mcp8765MCP memory server (persistent AI memory per developer)
qdrantqdrant/qdrant6333Vector store for AI memory semantic search
watchtowercontainrrr/watchtowerAutomatic container updates from GitHub Releases

Production Mode

cd ~/.tandemu # or wherever you cloned the repo docker compose up --build -d

This builds the backend and frontend into optimized Docker images and runs everything.

Development Mode

For hot-reload during development:

docker compose -f docker-compose.yml -f docker-compose.dev.yml up

This:

  • Starts infrastructure services (Postgres, ClickHouse, Redis, OTel Collector) normally
  • Runs the backend with tsc --watch + node --watch — restarts on TypeScript changes
  • Runs the frontend with next dev — instant hot module replacement
  • Mounts source code as volumes so edits are picked up immediately

Persistent Data

Five named volumes store persistent data:

VolumePath in ContainerData
postgres_data/var/lib/postgresql/dataOrganizations, users, teams, integrations
clickhouse_data/var/lib/clickhouseAll telemetry data
redis_data/dataCache (ephemeral, safe to lose)
openmemory_data/app/dataDeveloper memories (personality, coding preferences)
qdrant_data/qdrant/storageVector embeddings for AI memory search

To reset all data:

docker compose down -v

This removes all volumes. Next up starts fresh.

Updating

Tandemu uses Watchtower  for automatic updates. When a new version is published as a GitHub Release, updated container images are pushed to GHCR. Watchtower detects the new images and restarts the affected containers automatically.

Automatic updates

Watchtower runs as a service in the Docker Compose stack. By default, it polls for new images every 24 hours. Only containers labeled with com.centurylinklabs.watchtower.scope=tandemu are updated — infrastructure services (Postgres, ClickHouse, Redis) are never touched.

No configuration is needed. Automatic updates work out of the box.

Dashboard update banner

When a new release is available, the dashboard shows an update banner with the current and latest version, plus a link to the release notes. Organization Owners and Admins can click Update Now to trigger an immediate update via Watchtower’s HTTP API — no SSH or CLI access required.

The banner checks for updates on page load and caches the result for one hour to avoid GitHub API rate limits. You can dismiss it per-version.

Manual updates

If you prefer to update manually or Watchtower is not running:

docker compose pull docker compose up -d

Database migrations are applied automatically when the backend starts. As a fallback if auto-migration fails:

for f in packages/database/src/migrations/*.sql; do docker exec -i tandemu-postgres-1 psql -U tandemu -d tandemu < "$f" done

Disabling automatic updates

To disable Watchtower, remove or comment out the watchtower service in docker-compose.yml. You can still use the dashboard update banner for one-click manual updates, or pull images yourself.

Health Checks

Postgres, ClickHouse, and Redis have built-in health checks. The backend and frontend wait for Postgres and Redis to be healthy before starting.

Check status:

docker compose ps

All services should show Up or Up (healthy).

Last updated on