Docker Deployment Guide

Run your own prompts.chat instance using Docker Compose.

Views0
PublishedJan 31, 2026

Loading actions...

5 minBeginnerpromptSingle file

Skill content

Main instructions and any bundled files for this skill.

markdown

Docker Deployment Guide

Run your own prompts.chat instance using Docker Compose.

compose.yml supports both the pre-built container image being fetched from ghcr.io, or being built locally.

Quick Start

To build locally

git clone https://github.com/f/prompts.chat.git
cd prompts.chat
docker compose up -d --build

Open http://localhost:4444 in your browser.

Using a Pre-built Image

Simply remove the --build flag from the command:

git clone https://github.com/f/prompts.chat.git
cd prompts.chat
docker compose up -d

Standalone (Bring Your Own Database)

If you already have a PostgreSQL instance, you can run just the app container:

Need a hosted PostgreSQL database? We recommend Neon for serverless Postgres with connection pooling and database branching.

Sponsored by

Neon Logo fallback
docker build -f docker/Dockerfile -t prompts.chat .
docker run -d \
  --name prompts \
  -p 4444:3000 \
  -e DATABASE_URL="postgresql://user:pass@your-db-host:5432/prompts?schema=public" \
  -e AUTH_SECRET="$(openssl rand -base64 32)" \
  prompts.chat

Or if you simply want to use the pre-built image:

docker run -d \
  --name prompts \
  -p 4444:3000 \
  -e DATABASE_URL="postgresql://user:pass@your-db-host:5432/prompts?schema=public" \
  -e AUTH_SECRET="$(openssl rand -base64 32)" \
  ghcr.io/f/prompts.chat:latest

Custom Branding

All branding is configured via PCHAT_* environment variables at runtime -- no rebuild needed.

# compose.yml
services:
  app:
    environment:
      # ... existing vars ...
      PCHAT_NAME: "Acme Prompts"
      PCHAT_DESCRIPTION: "Our team's AI prompt library"
      PCHAT_COLOR: "#ff6600"
      PCHAT_AUTH_PROVIDERS: "github,google"
      PCHAT_LOCALES: "en,es,fr"

Then restart: docker compose up -d

Configuration Variables

All variables are prefixed with PCHAT_ to avoid conflicts.

Branding (branding.* in prompts.config.ts)

Env VariableConfig PathDescriptionDefault
PCHAT_NAMEbranding.nameApp name shown in UIMy Prompt Library
PCHAT_DESCRIPTIONbranding.descriptionApp descriptionCollect, organize...
PCHAT_LOGObranding.logoLogo path (in public/)/logo.svg
PCHAT_LOGO_DARKbranding.logoDarkDark mode logoSame as PCHAT_LOGO
PCHAT_FAVICONbranding.faviconFavicon path/logo.svg

Theme (theme.* in prompts.config.ts)

Env VariableConfig PathDescriptionDefault
PCHAT_COLORtheme.colors.primaryPrimary color (hex)#6366f1
PCHAT_THEME_RADIUStheme.radiusBorder radius: none|sm|md|lgsm
PCHAT_THEME_VARIANTtheme.variantUI style: default|flat|brutaldefault
PCHAT_THEME_DENSITYtheme.densitySpacing: compact|default|comfortabledefault

Authentication (auth.* in prompts.config.ts)

Env VariableConfig PathDescriptionDefault
PCHAT_AUTH_PROVIDERSauth.providersProviders: github,google,credentialscredentials
PCHAT_ALLOW_REGISTRATIONauth.allowRegistrationAllow public signuptrue

Internationalization (i18n.* in prompts.config.ts)

Env VariableConfig PathDescriptionDefault
PCHAT_LOCALESi18n.localesSupported locales (comma-separated)en
PCHAT_DEFAULT_LOCALEi18n.defaultLocaleDefault localeen

Features (features.* in prompts.config.ts)

Env VariableConfig PathDescriptionDefault
PCHAT_FEATURE_PRIVATE_PROMPTSfeatures.privatePromptsEnable private promptstrue
PCHAT_FEATURE_CHANGE_REQUESTSfeatures.changeRequestsEnable versioningtrue
PCHAT_FEATURE_CATEGORIESfeatures.categoriesEnable categoriestrue
PCHAT_FEATURE_TAGSfeatures.tagsEnable tagstrue
PCHAT_FEATURE_COMMENTSfeatures.commentsEnable commentstrue
PCHAT_FEATURE_AI_SEARCHfeatures.aiSearchEnable AI searchfalse
PCHAT_FEATURE_AI_GENERATIONfeatures.aiGenerationEnable AI generationfalse
PCHAT_FEATURE_MCPfeatures.mcpEnable MCP featuresfalse

System Environment Variables

VariableDescriptionDefault
AUTH_SECRETSecret for authentication tokensAuto-generated (set explicitly for production)
DATABASE_URLPostgreSQL connection stringSet in compose.yml
DIRECT_URLDirect PostgreSQL URL (bypasses poolers)Same as DATABASE_URL
PORTHost port mapping4444

Production Setup

For production, always set AUTH_SECRET explicitly:

# Generate a secret
export AUTH_SECRET=$(openssl rand -base64 32)

# Start with explicit secret
docker compose up -d

Or add it to a .env file next to compose.yml:

AUTH_SECRET=your-secret-key-here

With OAuth Providers

# compose.yml
services:
  app:
    environment:
      # ... existing vars ...
      PCHAT_AUTH_PROVIDERS: "github,google"
      AUTH_GITHUB_ID: "your-github-client-id"
      AUTH_GITHUB_SECRET: "your-github-client-secret"
      AUTH_GOOGLE_ID: "your-google-client-id"
      AUTH_GOOGLE_SECRET: "your-google-client-secret"

With AI Features (OpenAI)

# compose.yml
services:
  app:
    environment:
      # ... existing vars ...
      PCHAT_FEATURE_AI_SEARCH: "true"
      OPENAI_API_KEY: "sk-..."

Database Seeding

Seed the database with example prompts:

docker compose exec app npx prisma db seed

Mount your logo file into the app container:

# compose.yml
services:
  app:
    volumes:
      - ./my-logo.svg:/app/public/logo.svg
    environment:
      PCHAT_LOGO: "/logo.svg"

Data Persistence

PostgreSQL data is stored in the postgres_data named volume and persists across container restarts, rebuilds, and image updates.

Backup

# Backup database
docker compose exec db pg_dump -U prompts prompts > backup.sql

# Restore database
docker compose exec -T db psql -U prompts prompts < backup.sql

Building Locally

docker compose build
docker compose up -d

Health Check

The app container includes a health check endpoint:

curl http://localhost:4444/api/health

Response:

{
  "status": "healthy",
  "timestamp": "2024-01-01T00:00:00.000Z",
  "database": "connected"
}

Troubleshooting

View Logs

# All services
docker compose logs

# Follow logs
docker compose logs -f

# App logs only
docker compose logs app

# Database logs only
docker compose logs db

Database Access

# Connect to PostgreSQL
docker compose exec db psql -U prompts -d prompts

# Run a query
docker compose exec db psql -U prompts -d prompts -c "SELECT COUNT(*) FROM \"Prompt\""

Container Shell

docker compose exec app sh
docker compose exec db bash

Common Issues

App container keeps restarting:

  • Check logs: docker compose logs app
  • Database may not be ready yet -- the entrypoint retries for up to 60 seconds

Database connection errors:

  • Verify the db service is healthy: docker compose ps
  • Check database logs: docker compose logs db

Authentication issues:

  • Set AUTH_SECRET explicitly for production
  • For OAuth, verify callback URLs match your domain

Updating

# If using pre-built images
docker compose pull
docker compose up -d

# If building locally
git pull
docker compose build
docker compose up -d

Data persists in the postgres_data volume across updates.

Migrating from the Old Single-Image Setup

If you were using the previous all-in-one Docker image:

# 1. Export your database from the old container
docker exec prompts pg_dump -U prompts prompts > backup.sql

# 2. Stop and remove the old container
docker stop prompts && docker rm prompts

# 3. Start the new compose setup
docker compose up -d

# 4. Import your data
docker compose exec -T db psql -U prompts prompts < backup.sql

Resource Requirements

Runtime (after first build):

  • 1 CPU core
  • 1GB RAM
  • 2GB disk space

First-run build (Next.js compilation on startup):

  • 1 CPU core
  • Higher memory required (OOM may occur with low limits)
  • 2GB disk space

⚠️ If you see Killed followed by exited with code 137 during first startup, your Docker container likely ran out of memory during the build step. Increasing Docker's memory allocation (e.g., ~4GB or more) can help resolve this. On Docker Desktop: Settings → Resources → Memory.

Recommended for production:

  • 2 CPU cores
  • 2GB RAM (runtime)
  • 10GB disk space

Running Behind a Reverse Proxy

Nginx

server {
    listen 443 ssl http2;
    server_name prompts.example.com;

    ssl_certificate /etc/letsencrypt/live/prompts.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/prompts.example.com/privkey.pem;

    location / {
        proxy_pass http://localhost:4444;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
}

Caddy

prompts.example.com {
    reverse_proxy localhost:4444
}

Security Considerations

  1. Always set AUTH_SECRET in production
  2. Use HTTPS -- put a reverse proxy (Nginx, Caddy, Traefik) in front
  3. Change default database password -- update POSTGRES_PASSWORD in compose.yml and the connection strings
  4. Limit exposed ports -- only expose what's needed
  5. Regular updates -- pull the latest image regularly
  6. Backup data -- regularly backup the database

License

MIT

Share: