Docker Deployment Guide
Run your own prompts.chat instance using Docker Compose.
Overview
Docker Deployment Guide
Run your own prompts.chat instance using Docker Compose.
Quick Start
git clone https://github.com/f/prompts.chat.git
cd prompts.chat
docker compose up -d
Open http://localhost:4444 in your browser.
Using a Pre-built Image
Edit compose.yml and replace the build block with the published image:
services:
app:
# build:
# context: .
# dockerfile: docker/Dockerfile
image: ghcr.io/f/prompts.chat:latest
Then run:
docker compose up -d
Standalone (Bring Your Own Database)
If you already have a PostgreSQL instance, you can run just the app container:
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
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 Variable | Config Path | Description | Default |
|---|---|---|---|
PCHAT_NAME | branding.name | App name shown in UI | My Prompt Library |
PCHAT_DESCRIPTION | branding.description | App description | Collect, organize... |
PCHAT_LOGO | branding.logo | Logo path (in public/) | /logo.svg |
PCHAT_LOGO_DARK | branding.logoDark | Dark mode logo | Same as PCHAT_LOGO |
PCHAT_FAVICON | branding.favicon | Favicon path | /logo.svg |
Theme (theme.* in prompts.config.ts)
| Env Variable | Config Path | Description | Default |
|---|---|---|---|
PCHAT_COLOR | theme.colors.primary | Primary color (hex) | #6366f1 |
PCHAT_THEME_RADIUS | theme.radius | Border radius: `none\ | sm\ |
PCHAT_THEME_VARIANT | theme.variant | UI style: `default\ | flat\ |
PCHAT_THEME_DENSITY | theme.density | Spacing: `compact\ | default\ |
Authentication (auth.* in prompts.config.ts)
| Env Variable | Config Path | Description | Default |
|---|---|---|---|
PCHAT_AUTH_PROVIDERS | auth.providers | Providers: github,google,credentials | credentials |
PCHAT_ALLOW_REGISTRATION | auth.allowRegistration | Allow public signup | true |
Internationalization (i18n.* in prompts.config.ts)
| Env Variable | Config Path | Description | Default |
|---|---|---|---|
PCHAT_LOCALES | i18n.locales | Supported locales (comma-separated) | en |
PCHAT_DEFAULT_LOCALE | i18n.defaultLocale | Default locale | en |
Features (features.* in prompts.config.ts)
| Env Variable | Config Path | Description | Default |
|---|---|---|---|
PCHAT_FEATURE_PRIVATE_PROMPTS | features.privatePrompts | Enable private prompts | true |
PCHAT_FEATURE_CHANGE_REQUESTS | features.changeRequests | Enable versioning | true |
PCHAT_FEATURE_CATEGORIES | features.categories | Enable categories | true |
PCHAT_FEATURE_TAGS | features.tags | Enable tags | true |
PCHAT_FEATURE_COMMENTS | features.comments | Enable comments | true |
PCHAT_FEATURE_AI_SEARCH | features.aiSearch | Enable AI search | false |
PCHAT_FEATURE_AI_GENERATION | features.aiGeneration | Enable AI generation | false |
PCHAT_FEATURE_MCP | features.mcp | Enable MCP features | false |
System Environment Variables
| Variable | Description | Default |
|---|---|---|
AUTH_SECRET | Secret for authentication tokens | Auto-generated (set explicitly for production) |
DATABASE_URL | PostgreSQL connection string | Set in compose.yml |
DIRECT_URL | Direct PostgreSQL URL (bypasses poolers) | Same as DATABASE_URL |
PORT | Host port mapping | 4444 |
Production Setup
For production, always set AUTH_SECRET explicitly:
# Generate a secret
# 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
Custom Logo
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
dbservice is healthy:docker compose ps - Check database logs:
docker compose logs db
Authentication issues:
- Set
AUTH_SECRETexplicitly 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
Killedfollowed byexited with code 137during 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
- Always set AUTH_SECRET in production
- Use HTTPS -- put a reverse proxy (Nginx, Caddy, Traefik) in front
- Change default database password -- update
POSTGRES_PASSWORDin compose.yml and the connection strings - Limit exposed ports -- only expose what's needed
- Regular updates -- pull the latest image regularly
- Backup data -- regularly backup the database
License
MIT