Skip to content

Docker Deployment

Production-ready Docker deployment guide for DesterLib.

macOS/Linux:

Terminal window
curl -fsSL https://raw.githubusercontent.com/DesterLib/desterlib/main/scripts/setup/unix.sh | bash

Windows (PowerShell):

Terminal window
iwr -useb https://raw.githubusercontent.com/DesterLib/desterlib/main/scripts/setup/windows.ps1 | iex

The setup script configures production-ready settings by default:

  • Sets NODE_ENV=production
  • Configures restart policies
  • Sets up health checks
  • Uses production database
Terminal window
git clone https://github.com/DesterLib/desterlib.git
cd desterlib
# Create .env in apps/api/
DATABASE_URL=postgresql://desterlib:STRONG_PASSWORD@postgres:5432/desterlib?schema=public
NODE_ENV=production
PORT=3001
# Start in production mode
docker compose up -d

Add resource limits to prevent overconsumption:

Edit docker-compose.yml:

api:
image: desterlib/api:latest
deploy:
resources:
limits:
cpus: "2.0"
memory: 2G
reservations:
memory: 512M
postgres:
image: postgres:15-alpine
deploy:
resources:
limits:
memory: 1G
reservations:
memory: 256M

Ensure data persists across container restarts:

volumes:
postgres_data:
driver: local
driver_opts:
type: none
device: /path/to/persistent/storage
o: bind

Both services include health checks by default:

api:
healthcheck:
test:
[
"CMD-SHELL",
"wget --no-verbose --tries=1 --spider http://localhost:3001/health || exit 1",
]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
postgres:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U desterlib"]
interval: 10s
timeout: 5s
retries: 5

The default configuration binds to 0.0.0.0:

ports:
- "0.0.0.0:3001:3001"

This allows connections from:

  • Local machine
  • LAN devices
  • Remote clients (if port forwarded)

For localhost-only access:

ports:
- "127.0.0.1:3001:3001"

nginx.conf:

server {
listen 80;
server_name desterlib.yourdomain.com;
location / {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# WebSocket support
location /ws {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}

Caddyfile:

desterlib.yourdomain.com {
reverse_proxy localhost:3001
}

Caddy automatically handles:

  • HTTPS certificates (Let’s Encrypt)
  • Certificate renewal
  • HTTP to HTTPS redirect

docker-compose.yml:

api:
image: desterlib/api:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.desterlib.rule=Host(`desterlib.yourdomain.com`)"
- "traefik.http.routers.desterlib.entrypoints=websecure"
- "traefik.http.routers.desterlib.tls.certresolver=myresolver"

Set in environment:

NODE_ENV=production # Less verbose
# or
NODE_ENV=development # More verbose (debug logs)

Use JSON log format:

api:
image: desterlib/api:latest
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

To syslog:

logging:
driver: syslog
options:
syslog-address: "tcp://192.168.1.100:514"

To file:

logging:
driver: json-file
options:
max-size: "100m"
max-file: "5"
compress: "true"

View health status:

Terminal window
docker ps

Look for “healthy” in the STATUS column.

Prometheus integration is planned for future releases.

Create isolated Docker network:

networks:
desterlib-net:
driver: bridge
internal: false
services:
postgres:
networks:
- desterlib-net
api:
networks:
- desterlib-net

Media is mounted read-only for security:

volumes:
- /path/to/media:/media:ro # :ro = read-only

Running as non-root user is planned for future releases.

Current setup is designed for single-server deployment:

  • One API instance
  • One PostgreSQL instance
  • Suitable for personal use (1-100 users)

Horizontal scaling is planned for future releases with:

  • Multiple API instances behind load balancer
  • Shared PostgreSQL database
  • Redis for session management

Create backup service:

# Add to docker-compose.yml
backup:
image: postgres:15-alpine
depends_on:
- postgres
volumes:
- ./backups:/backups
- postgres_data:/var/lib/postgresql/data:ro
command: >
sh -c "while true; do
pg_dump -U desterlib -h postgres desterlib > /backups/backup-$$(date +%Y%m%d-%H%M%S).sql
sleep 86400
done"
restart: unless-stopped

This creates daily backups in ./backups/.

Currently, updates require brief downtime:

Terminal window
cd ~/.desterlib
docker compose pull
docker compose up -d

Downtime: ~10-30 seconds during container restart.

Recommend updating during low-usage times:

Terminal window
# Schedule with cron at 3 AM
0 3 * * 0 cd ~/.desterlib && docker compose pull && docker compose up -d

Check logs:

Terminal window
docker compose logs --tail=100 api

Common causes:

  • Database connection failure
  • Invalid environment variables
  • Port already in use
  • Missing required config

Check resource usage:

Terminal window
docker stats

If too high:

  1. Add memory limits (see Resource Limits above)
  2. Check for memory leaks in logs
  3. Restart containers: docker compose restart

For large libraries (10,000+ items):

  1. Increase database resources:

    postgres:
    deploy:
    resources:
    limits:
    memory: 2G
  2. Optimize PostgreSQL:

    postgres:
    command: postgres -c shared_buffers=256MB -c max_connections=200