Skip to main content

Docker Compose Setup

This guide walks through a production-ready Docker Compose deployment of OpenCLM.

Repository Structure

openclm/
├── docker-compose.yml ← the main compose file
├── docker-compose.dev.yml ← development overrides
├── .env.example ← environment template
├── server/ ← API server source
├── src/ ← React frontend source
└── deploy/
├── nginx/ ← Nginx reverse proxy configs
└── caddy/ ← Caddy reverse proxy config

Step 1 — Clone and configure

git clone https://github.com/nxglabs/openclm.git
cd openclm
cp .env.example .env

Edit .env — see Environment Variables for all options.

Step 2 — docker-compose.yml

The default docker-compose.yml defines:

services:
db:
image: postgres:15-alpine
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5

keycloak:
image: quay.io/keycloak/keycloak:22
restart: unless-stopped
command: start
environment:
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://db/${POSTGRES_DB}
KC_DB_USERNAME: ${POSTGRES_USER}
KC_DB_PASSWORD: ${POSTGRES_PASSWORD}
KC_HOSTNAME: ${APP_URL}
KEYCLOAK_ADMIN: ${KC_ADMIN_USER}
KEYCLOAK_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD}
depends_on:
db:
condition: service_healthy

api:
image: ghcr.io/nxglabs/openclm-api:latest
restart: unless-stopped
environment:
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db/${POSTGRES_DB}
JWT_SECRET: ${JWT_SECRET}
KEYCLOAK_URL: http://keycloak:8080
APP_URL: ${APP_URL}
depends_on:
db:
condition: service_healthy

app:
image: ghcr.io/nxglabs/openclm-app:latest
restart: unless-stopped
environment:
VITE_API_URL: ${APP_URL}/api
VITE_KEYCLOAK_URL: ${APP_URL}/auth
ports:
- "3000:3000"
depends_on:
- api

volumes:
pgdata:

Step 3 — Start services

docker compose up -d

Watch the logs to confirm all services start cleanly:

docker compose logs -f

Step 4 — Initialise the database

# Run Prisma migrations
docker compose exec api npx prisma migrate deploy

# Seed default roles and admin user
docker compose exec api npx prisma db seed

Step 5 — Set up the reverse proxy

openclm.yourdomain.com {
reverse_proxy /auth/* keycloak:8080
reverse_proxy /api/* api:4000
reverse_proxy /* app:3000
}

Run Caddy:

docker run -d -p 80:80 -p 443:443 \
-v $PWD/deploy/caddy/Caddyfile:/etc/caddy/Caddyfile \
caddy:2-alpine

Nginx

See /deploy/nginx/openclm.conf in the repository for a production Nginx config.

Step 6 — Verify

Navigate to https://openclm.yourdomain.com in your browser.

Log in with:

Updating OpenCLM

Pull the latest images and restart:

docker compose pull
docker compose up -d
docker compose exec api npx prisma migrate deploy

:::tip Zero-downtime updates For zero-downtime updates, use a rolling deployment strategy with Docker Swarm or Kubernetes instead of Docker Compose. :::

Backup & Restore

See Database Backup for Postgres backup procedures.