Install and configureDocker Compose

Install with Docker Compose

Run SlugBase with Docker Compose using the published image: copy a compose file, set .env, persist data, optional PostgreSQL.

What you need

  • Docker and Docker Compose v2.
  • An .env file with production secrets and URLs — see Configuration.

You do not need to clone the SlugBase GitHub repository to run the pre-built image. Save the compose file below as docker-compose.yml next to your .env. Clone the repo only if you want to build the image from source instead of pulling mdglabs/slugbase:latest.

Docker Compose file

Save this as docker-compose.yml in an empty directory (for example slugbase/). It matches the docker-compose.example.yml shipped in the SlugBase repository if you prefer to copy from git later.

services:
  slugbase:
    image: mdglabs/slugbase:latest
    container_name: slugbase
    # To build from a local clone instead of pulling: add `build: .` (Compose builds and tags as the image above).
    ports:
      - "${PORT:-5000}:5000"
    env_file:
      - .env
    environment:
      # Override DB_PATH to use container path (required for SQLite)
      - DB_PATH=/app/data/slugbase.db
    volumes:
      # Mount data directory to persist SQLite database
      - ./data:/app/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "node", "-e", "require('http').get('http://localhost:5000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"]
      interval: 30s
      timeout: 3s
      start_period: 5s
      retries: 3

  # Optional PostgreSQL service (uncomment if using PostgreSQL instead of SQLite)
  # slugbase-postgres:
  #   image: postgres:16-alpine
  #   environment:
  #     - POSTGRES_DB=${DB_NAME:-slugbase}
  #     - POSTGRES_USER=${DB_USER:-slugbase}
  #     - POSTGRES_PASSWORD=${DB_PASSWORD:-change-this-password}
  #   volumes:
  #     - postgres-data:/var/lib/postgresql/data
  #   restart: unless-stopped
  #   healthcheck:
  #     test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-slugbase}"]
  #     interval: 10s
  #     timeout: 5s
  #     retries: 5
  #
  # If using PostgreSQL, update the slugbase service:
  # slugbase:
  #   ...
  #   depends_on:
  #     slugbase-postgres:
  #       condition: service_healthy

# volumes:
#   postgres-data:

Steps

Create the project directory and files

Create a folder for this deployment, add docker-compose.yml (from the block above), and create .env with at least JWT_SECRET, ENCRYPTION_KEY, and SESSION_SECRET (production length requirements apply). Set BASE_URL and FRONTEND_URL to your public site URL when deploying behind a domain.

mkdir -p ./data

The compose file mounts ./data to /app/data so the SQLite file survives container restarts.

Start the stack

From the directory that contains docker-compose.yml and .env:

docker compose up -d

The service pulls mdglabs/slugbase:latest from Docker Hub by default, publishes ${PORT:-5000}:5000, loads env_file: .env, sets DB_PATH=/app/data/slugbase.db inside the container, and defines a healthcheck against /api/health.

Open the app

Visit http://localhost:5000 (or your host and mapped port). Complete First run setup when the database is new.

Optional PostgreSQL

Uncomment the slugbase-postgres service and bottom volumes in your docker-compose.yml, then set PostgreSQL-related variables in .env. Wire the app service with depends_on and health as shown in the comments above.

# In .env when using Postgres (adjust user, password, and db name to match compose)
DB_TYPE=postgresql
DATABASE_URL=postgresql://slugbase:your-password@slugbase-postgres:5432/slugbase

Build from source instead of Docker Hub

If you have a local clone of the repository, you can build the image from the Dockerfile at the repo root: add build: . to the slugbase service (and optionally comment out or align image: with your build tag). Use the same docker-compose.example.yml in the repo, or start from the file on this page.

Verify

CheckExpected
docker compose psService healthy after start period.
BrowserInitial Setup or login at your base URL.
LogsNo repeated crash loops; address validation errors if secrets are missing.

Troubleshooting