Skip to content
decodecodeveloper docs
Studio → Deploy and self-host Studio → Deploy

Docker Compose

Deploy deco Studio locally using Docker Compose for testing and development

This guide covers running deco Studio with Docker Compose for testing and self-hosted evaluation.

Source (compose files): decocms/studio → deploy/docker-compose

Overview

Studio uses PostgreSQL as its database. The repo ships three compose files under deploy/docker-compose/ — pick by use case:

  • docker-compose.postgres.yml — self-host, all-in-one: Studio (published image) plus a fully bundled stack (PostgreSQL + NATS + MinIO), all wired so the app provisions nothing itself. The recommended starting point. (selfhost/examples/docker-compose wraps this with a documented .env.example.)
  • docker-compose.yml — self-host, bring-your-own DB: Studio only (published image), expecting a PostgreSQL you provide.
  • docker-compose.dev.yml — development: only the dependencies (PostgreSQL + a 3-node NATS cluster, prod-like topology); you run the API and web apps from source with bun run dev:servers. No sandbox here — that needs Kubernetes (see the dev-hybrid loop).

The self-host files use a Docker volume for persistence and an automatic /health check.

Prerequisites

  • Docker 20.10+
  • Docker Compose 2.0+
  • A PostgreSQL database — bundled (via docker-compose.postgres.yml) or your own

Quick Start (bundled PostgreSQL)

# 1. Clone the repo and enter the compose directory
git clone https://github.com/decocms/studio.git
cd studio/deploy/docker-compose
 
# 2. Create a .env with an auth secret, a vault key, and Postgres credentials
cat > .env << EOF
BETTER_AUTH_SECRET=$(openssl rand -base64 32)
ENCRYPTION_KEY=$(openssl rand -base64 32)
POSTGRES_USER=studio_user
POSTGRES_PASSWORD=$(openssl rand -base64 24)
POSTGRES_DB=studio_db
EOF
 
# 3. Start Studio + PostgreSQL
docker compose -f docker-compose.postgres.yml up -d
 
# 4. Access
open http://localhost:3000

The docker-compose.postgres.yml file wires DATABASE_URL automatically from the POSTGRES_* variables, using the postgres service as the host.

BETTER_AUTH_SECRET and ENCRYPTION_KEY both fall back to insecure dev-only defaults if unset — always set real values for anything shared. The POSTGRES_* variables also have defaults, but always set a real password.

Environment variables

Set these in .env alongside the compose file:

VariableDefaultDescription
BETTER_AUTH_SECRETlocal-dev-better-auth-secret-change-me (insecure)Authentication secret — always set a real one. Generate with openssl rand -base64 32
ENCRYPTION_KEYdeterministic dev-only fallback (insecure)Credential-vault key for encrypting stored secrets/tokens — must stay stable across restarts. Always set a real one for anything shared.
IMAGE_REPOSITORYghcr.io/decocms/studio/studioImage repository
IMAGE_TAGlatestImage tag
PORT3000Port exposed on the host
BASE_URL / BETTER_AUTH_URLhttp://localhost:3000Public URLs for the app
DATABASE_URLsee belowPostgreSQL connection string
POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DBstudio / studio / studioCredentials for the bundled Postgres (postgres compose file only)

The container runs as user 1001:1001 and persists data to the studio-data volume; the bundled Postgres persists to postgres-data.

Using your own PostgreSQL

To point Studio at an external database, use the base docker-compose.yml and set DATABASE_URL:

# .env
BETTER_AUTH_SECRET=your_generated_secret_here
DATABASE_URL=postgresql://user:password@host:5432/database_name
docker compose up -d

localhost inside the container refers to the container itself. To reach PostgreSQL running on your machine, use host.docker.internal (Docker Desktop) or your machine's LAN IP. With the bundled docker-compose.postgres.yml, the host is the service name postgres.

Authentication options

By default the bundled stack uses email/password auth. To enable social login, uncomment and set the provider variables in the compose environment block (or your .env):

AUTH_GOOGLE_CLIENT_ID=...
AUTH_GOOGLE_CLIENT_SECRET=...
AUTH_GITHUB_CLIENT_ID=...
AUTH_GITHUB_CLIENT_SECRET=...

For richer configuration (deployment-wide SSO, email providers, magic links), set the corresponding AUTH_* variables in the compose environment block — there's no config file to mount. See Authentication for the full reference.

Operations

Logs and status

# Follow logs for the app
docker compose logs -f studio
 
# Container status
docker compose ps
 
# Resource usage (container name is "decocms")
docker stats decocms

Update the image

docker compose pull
docker compose up -d

Pin a version by setting IMAGE_TAG in .env before pulling.

Backup and restore (PostgreSQL)

# Backup (bundled Postgres service)
docker compose exec postgres pg_dump -U studio_user studio_db > backup-$(date +%Y%m%d).sql
 
# Restore
docker compose exec -T postgres psql -U studio_user studio_db < backup-20240101.sql

Reset all data

docker compose down -v   # removes named volumes (studio-data, postgres-data)
docker compose -f docker-compose.postgres.yml up -d

docker compose down -v permanently deletes the volumes. Back up first if the data matters. Plain docker compose down (without -v) keeps your volumes.

Security

  • Always generate strong BETTER_AUTH_SECRET and ENCRYPTION_KEY values (openssl rand -base64 32) and a real POSTGRES_PASSWORD.
  • Don't commit .env (echo ".env" >> .gitignore; chmod 600 .env).
  • Don't commit secrets (client secrets, API keys) into .env or the compose file.