Files
plunk/apps/wiki/content/docs/self-hosting/docker.mdx
T

395 lines
8.4 KiB
Plaintext

---
title: Docker Deployment
description: Deploy Plunk with Docker Compose
---
## Prerequisites
- Docker installed
- Docker Compose installed
- Git installed
## Quick Start
### 1. Clone Repository
```bash
git clone https://github.com/useplunk/plunk.git
cd plunk
```
### 2. Copy Environment File
```bash
cp .env.self-host.example .env
```
### 3. Configure Environment
Edit `.env` and configure required variables:
```bash
# Database Password (PostgreSQL)
DB_PASSWORD="changeme123"
# JWT Secret (generate with: openssl rand -base64 32)
JWT_SECRET="your-secret-here"
# Domains (for subdomain-based routing)
API_DOMAIN="api.localhost"
DASHBOARD_DOMAIN="app.localhost"
LANDING_DOMAIN="www.localhost"
WIKI_DOMAIN="docs.localhost"
# Set to 'true' for HTTPS in production
USE_HTTPS="false"
# AWS SES (for email sending)
AWS_SES_REGION="us-east-1"
AWS_SES_ACCESS_KEY_ID="your-access-key"
AWS_SES_SECRET_ACCESS_KEY="your-secret-key"
SES_CONFIGURATION_SET="plunk-configuration-set"
# S3-compatible storage (Minio is included by default)
# Leave defaults unless using external S3
S3_ENDPOINT="http://minio:9000"
S3_ACCESS_KEY_ID="plunk"
S3_ACCESS_KEY_SECRET="plunkminiopass"
S3_BUCKET="uploads"
S3_PUBLIC_URL="http://localhost:9000/uploads"
S3_FORCE_PATH_STYLE="true"
```
### 4. Start Services
```bash
docker compose up -d
```
This starts:
- PostgreSQL database
- Redis
- Minio (S3-compatible storage)
- Plunk application (all services in one container with nginx)
- API server
- Worker process
- Web dashboard
- Landing page
- Documentation
### 5. Access Services
The services are available at the configured domains:
- **Dashboard**: `http://app.localhost` (or your configured domain)
- **API**: `http://api.localhost`
- **Landing**: `http://www.localhost`
- **Docs**: `http://docs.localhost`
- **Minio Console**: `http://localhost:9001`
Create your first account and start sending emails!
## Docker Compose Configuration
The `docker-compose.yml` file uses the pre-built Plunk image from GitHub Container Registry:
```yaml
version: '3.8'
services:
postgres:
image: postgres:16-alpine
container_name: plunk-postgres
restart: unless-stopped
environment:
POSTGRES_DB: plunk
POSTGRES_USER: plunk
POSTGRES_PASSWORD: ${DB_PASSWORD:-changeme123}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- plunk
redis:
image: redis:7-alpine
container_name: plunk-redis
restart: unless-stopped
command: redis-server --appendonly yes
volumes:
- redis_data:/data
networks:
- plunk
minio:
image: minio/minio:latest
container_name: plunk-minio
restart: unless-stopped
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-plunk}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-plunkminiopass}
volumes:
- minio_data:/data
ports:
- "9000:9000" # API
- "9001:9001" # Console
networks:
- plunk
plunk:
image: ghcr.io/useplunk/plunk:latest
container_name: plunk
restart: unless-stopped
environment:
SERVICE: all # Runs all services (API, Worker, Web, Landing, Wiki)
DATABASE_URL: postgresql://plunk:${DB_PASSWORD}@postgres:5432/plunk
REDIS_URL: redis://redis:6379
JWT_SECRET: ${JWT_SECRET}
# Domain configuration for subdomain routing
API_DOMAIN: ${API_DOMAIN:-api.localhost}
DASHBOARD_DOMAIN: ${DASHBOARD_DOMAIN:-app.localhost}
LANDING_DOMAIN: ${LANDING_DOMAIN:-www.localhost}
WIKI_DOMAIN: ${WIKI_DOMAIN:-docs.localhost}
USE_HTTPS: ${USE_HTTPS:-false}
# AWS SES
AWS_SES_REGION: ${AWS_SES_REGION}
AWS_SES_ACCESS_KEY_ID: ${AWS_SES_ACCESS_KEY_ID}
AWS_SES_SECRET_ACCESS_KEY: ${AWS_SES_SECRET_ACCESS_KEY}
# S3/Minio storage
S3_ENDPOINT: ${S3_ENDPOINT:-http://minio:9000}
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-plunk}
S3_ACCESS_KEY_SECRET: ${S3_ACCESS_KEY_SECRET:-plunkminiopass}
ports:
- "465:465" # SMTP (implicit TLS)
- "587:587" # SMTP (STARTTLS)
depends_on:
- postgres
- redis
- minio
networks:
- plunk
volumes:
postgres_data:
redis_data:
minio_data:
plunk_data:
networks:
plunk:
driver: bridge
```
**Note**: The Plunk image contains all applications (API, Worker, Web, Landing, Wiki) and uses nginx for subdomain-based routing.
## Production Deployment
### Using Pre-built Image
The easiest way to deploy is using the pre-built image from GitHub Container Registry:
```bash
docker pull ghcr.io/useplunk/plunk:latest
docker compose up -d
```
### Building Your Own Image
If you want to build from source:
```bash
docker build -t plunk:custom .
```
Then update `docker-compose.yml` to use your custom image:
```yaml
plunk:
image: plunk:custom
# ... rest of configuration
```
### Security Hardening
1. **Use strong passwords**
```bash
DB_PASSWORD=$(openssl rand -base64 32)
JWT_SECRET=$(openssl rand -base64 32)
```
2. **Use HTTPS**
- Set `USE_HTTPS=true` in your `.env`
- Set up reverse proxy (Traefik, Caddy, or nginx)
- Configure SSL certificates (Let's Encrypt)
3. **Configure domains**
```bash
API_DOMAIN=api.yourdomain.com
DASHBOARD_DOMAIN=app.yourdomain.com
LANDING_DOMAIN=www.yourdomain.com
WIKI_DOMAIN=docs.yourdomain.com
USE_HTTPS=true
```
4. **Restrict network access**
- Don't expose database and Redis ports publicly
- Use internal Docker networks
- Only expose port 80/443 (via reverse proxy) and SMTP ports
5. **Regular backups**
- Database backups (automated via cron)
- Minio data backups
### Scaling
The Plunk image runs all services in a single container by default. For higher scale:
#### Separate Services
You can run services separately by setting the `SERVICE` environment variable:
```yaml
# API only
plunk-api:
image: ghcr.io/useplunk/plunk:latest
environment:
SERVICE: api
# ... configuration
# Worker only
plunk-worker:
image: ghcr.io/useplunk/plunk:latest
environment:
SERVICE: worker
# ... configuration
# Web only
plunk-web:
image: ghcr.io/useplunk/plunk:latest
environment:
SERVICE: web
# ... configuration
```
#### Scale Workers
For higher email throughput, run multiple worker containers:
```bash
docker compose up -d --scale plunk-worker=3
```
#### External Services
For production at scale, use managed services:
- Managed PostgreSQL (AWS RDS, DigitalOcean, Supabase)
- Managed Redis (AWS ElastiCache, Redis Cloud, Upstash)
- AWS S3 (instead of Minio)
## Maintenance
### View Logs
```bash
# All services
docker compose logs -f
# Specific service
docker compose logs -f plunk
docker compose logs -f postgres
```
### Restart Services
```bash
docker compose restart plunk
```
### Update Plunk
Pull the latest image and restart:
```bash
docker compose pull plunk
docker compose up -d plunk
```
If you built from source:
```bash
git pull
docker build -t plunk:custom .
docker compose up -d
```
### Backup Database
```bash
docker compose exec postgres pg_dump -U plunk plunk > backup-$(date +%Y%m%d).sql
```
### Restore Database
```bash
docker compose exec -T postgres psql -U plunk plunk < backup.sql
```
### Backup Minio Data
```bash
docker compose exec minio mc alias set local http://localhost:9000 plunk plunkminiopass
docker compose exec minio mc mirror local/uploads /backups/minio
```
## Troubleshooting
### Services won't start
Check logs:
```bash
docker compose logs plunk
```
### Database connection errors
Ensure DATABASE_URL is correct and database is running:
```bash
docker compose ps postgres
docker compose exec postgres psql -U plunk -d plunk -c "SELECT 1;"
```
### Worker not processing jobs
Check Plunk container logs for worker output:
```bash
docker compose logs plunk | grep worker
```
Verify Redis connection:
```bash
docker compose exec redis redis-cli PING
```
### Cannot access services
Check that your domains resolve correctly:
```bash
# For local development with *.localhost domains, these should work automatically
# For production domains, ensure DNS is configured correctly
curl http://api.localhost
curl http://app.localhost
```
### Minio not accessible
Check Minio is running:
```bash
docker compose ps minio
docker compose logs minio
```
Access Minio console at `http://localhost:9001` with credentials from `.env`.
## Next Steps
- [Configure environment variables](/self-hosting/environment-variables)
- [Set up email delivery](/self-hosting/email-setup)
- [Database setup and migrations](/self-hosting/database-setup)