Docker Deployment
Deploy Velist with Docker. Includes multi-stage build, WAL mode support, and auto-backup.
Deployment Time
Docker deployment memiliki downtime lebih lama (30-70 detik) dibanding PM2 native (3-5 detik) karena proses build image. Untuk production yang memerlukan deploy cepat, pertimbangkan PM2 Native Deployment.
Quick Start
Files Already Included
Dockerfile dan docker-compose.yml sudah tersedia di root project. Tidak perlu membuat manual.
# Clone project
git clone https://github.com/yourusername/your-velist-app.git
cd your-velist-app
# Edit environment variables
nano .env
# Build and run
docker-compose up -d --build
# Check logs
docker-compose logs -fConfiguration
Environment File
Create .env:
# Required
JWT_SECRET=your-super-secret-random-string-min-32-chars
# Optional: S3 Backup
BACKUP_S3_ENABLED=false
# BACKUP_S3_PATH=backups/database
# S3_BUCKET=your-bucket
# S3_REGION=us-east-1
# S3_ENDPOINT=https://s3.wasabisys.com
# S3_ACCESS_KEY=xxx
# S3_SECRET_KEY=xxx
# Optional: S3 Storage
# STORAGE_DRIVER=s3Run
# First time
docker-compose up -d --build
# View logs
docker-compose logs -f
# Check health
curl http://localhost:3000/healthDatabase Persistence (WAL Mode)
Velist menggunakan WAL mode (Write-Ahead Logging) yang menghasilkan 3 file:
db/
├── prod.sqlite # Main database
├── prod.sqlite-wal # Write-ahead log
└── prod.sqlite-shm # Shared memoryVolume mount harus mencakup semua 3 file:
volumes:
- ./db:/app/dbJangan mount file individual, mount seluruh folder:
# ❌ Salah - WAL files tidak tersimpan
volumes:
- ./db.sqlite:/app/db.sqlite
# ✅ Benar - Semua file tersimpan
volumes:
- ./db:/app/dbBackup dalam Docker
Auto-backup berjalan di dalam container. Backup disimpan di:
storage/backups/
└── backup-2024-01-15T10-30-00-000Z.sqliteVolume mount untuk backup:
volumes:
- ./storage:/app/storageAkses backup dari host:
# List backups
ls -la storage/backups/
# Copy backup
mkdir -p /host/backup
cp storage/backups/backup-xxx.sqlite /host/backup/Production Deployment
1. VPS Setup
# SSH ke VPS
ssh root@your-vps-ip
# Install Docker
curl -fsSL https://get.docker.com | sh
# Install Docker Compose
apt install docker-compose-plugin
# Clone project
git clone https://github.com/yourusername/your-velist-app.git
cd your-velist-app2. Configure Environment
# Create .env file
JWT_SECRET=$(openssl rand -base64 32)
echo "JWT_SECRET=$JWT_SECRET" > .env
# Edit other settings as needed
nano .env3. Start
docker-compose up -d --build
# Check status
docker-compose ps
# View logs
docker-compose logs -f4. Update Deployment
# Pull latest
git pull
# Rebuild and restart
docker-compose up -d --build
# Clean old images
docker image prune -fCloudflare + Docker
Kalau pakai Cloudflare Proxy dengan Docker:
# docker-compose.yml
services:
app:
build: .
ports:
- "3000:3000" # Cloudflare Origin Rules → 3000
# ... rest of configCloudflare Setup:
- DNS A record → VPS IP (Proxied)
- SSL/TLS: Flexible (Docker tidak perlu SSL cert)
- Origin Rules: Port 3000
Lihat detail di Cloudflare Proxy Guide
Reverse Proxy (Optional)
Kalau butuh multiple services atau custom routing:
version: '3.8'
services:
app:
build: .
expose:
- "3000"
environment:
- PORT=3000
volumes:
- ./db:/app/db
- ./storage:/app/storage
restart: unless-stopped
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- app
restart: unless-stoppedTapi kalau pakai Cloudflare Proxy, tidak perlu Nginx!
Deployment Checklist
- [ ]
.envfile dengan JWT_SECRET - [ ] Database volume:
./db:/app/db - [ ] Storage volume:
./storage:/app/storage - [ ] Container running:
docker-compose ps - [ ] Health check pass:
curl http://localhost:3000/health - [ ] Backup folder exists:
ls storage/backups/ - [ ] (Optional) S3 configured untuk offsite backup
Update Deployment
Long Downtime Warning
Update dengan Docker memerlukan build ulang yang menyebabkan downtime 30-70 detik.
Standard Update (with downtime)
# 1. Backup dulu
cp -r db db-backup-$(date +%Y%m%d)
# 2. Pull latest code
git pull
# 3. Stop, rebuild, start (downtime ~30-70 detik)
docker-compose down
docker-compose up -d --build
# 4. Migration (kalau ada)
docker-compose exec app bun run db:migrate
# 5. Check status
docker-compose psBuild time breakdown:
docker-compose up --build
├── Download base image: 2-5 detik
├── Install dependencies: 20-30 detik ← PALING LAMA
├── Build frontend: 10-20 detik
└── Start container: 3-5 detik
TOTAL: ~35-60 detik downtimeFaster Update dengan Pre-built Image
Push image ke registry (Docker Hub, GHCR, etc), lalu pull di VPS:
# Di CI/CD atau local development
docker build -t yourname/velist-app:v2.0 .
docker push yourname/velist-app:v2.0
# Di VPS (hanya pull, tidak perlu build)
docker-compose down
docker pull yourname/velist-app:v2.0 # 5-10 detik
docker-compose up -d # 3 detik
# Total downtime: ~10-15 detikdocker-compose.yml untuk pre-built:
services:
app:
image: yourname/velist-app:v2.0 # ← Pre-built image
# build: . # ← Comment out
ports:
- "3000:3000"
# ... rest of configDocker vs PM2 Comparison
| Aspek | Docker | PM2 Native |
|---|---|---|
| Setup complexity | Medium | Simple |
| Deployment time | ⚠️ 30-70 detik | ✅ 3-5 detik |
| Downtime | ⚠️ Long (build) | ✅ Short (restart) |
| Isolation | ✅ Containerized | ❌ Process only |
| Portability | ✅ Run anywhere | ⚠️ Need Bun installed |
| Multi-service | ✅ Easy with Compose | ❌ Manual setup |
| SQLite support | ✅ Volume mount | ✅ Native file |
When to Use Docker
✅ Cocok untuk:
- Development environment consistency
- Multi-service apps (app + redis + etc)
- Kubernetes deployment
- CI/CD pipeline dengan registry
- Teams yang familiar Docker
When to Use PM2 Native
✅ Cocok untuk:
- Production deployment cepat
- Single VPS sederhana
- SQLite-only apps
- Low traffic websites
- Quick iteration/development
Recommendation by Scenario
| Scenario | Recommended | Why |
|---|---|---|
| Startup/Side project | PM2 | Deploy cepat, simple |
| Production app | PM2 atau Docker + Registry | Minimal downtime |
| Multi-service | Docker | Compose orchestration |
| Kubernetes | Docker | Container standard |
| Team dev | Docker | Consistent environment |
Useful Commands
# View logs
docker-compose logs -f
# Restart
docker-compose restart
# Shell into container
docker-compose exec app /bin/bash
# Run migrations manually
docker-compose exec app bun run db:migrate
# Backup database manually
docker-compose exec app bun -e "
const { backupService } = require('./src/features/backup/service');
backupService.performBackup().then(console.log);
"
# View running containers
docker ps
# Stop
docker-compose down
# Stop and remove volumes (DANGER - data lost!)
docker-compose down -vTroubleshooting
Container won't start
# Check logs
docker-compose logs
# Common issues:
# 1. JWT_SECRET not set
# 2. Port 3000 already in use
# 3. Permission denied on volumesDatabase locked or WAL errors
# WAL files mungkin corrupt
# Fix: Delete WAL files (data terakhir mungkin hilang)
docker-compose down
rm db/*.sqlite-wal db/*.sqlite-shm
docker-compose up -dBackup not running
# Check backup service logs
docker-compose logs | grep "\[Backup\]"
# Check if BACKUP_ENABLED=true
docker-compose exec app env | grep BACKUPPermission denied on volumes
# Fix permissions
sudo chown -R 1000:1000 db/ storage/See Also
- Cloudflare Proxy - Deploy tanpa Nginx
- Backup - Auto-backup configuration
- Production - Native VPS deployment (non-Docker)