Files
2026-10-01 13:23:45 +07:00

8.9 KiB
Raw Permalink Blame History

Docker Deployment Guide

Deploy dashboard-cpsp with Docker Compose. Layout mirrors the legacy dashboard/ stack (Postgres + API + Nginx frontend), adapted for Django + Gunicorn and a separate cron container.

Architecture

┌──────────────────────────────────────────────────────────────┐
│                        Host Server                            │
│                                                               │
│  ┌─────────────┐   /api/*    ┌──────────────┐                │
│  │  frontend   │────────────►│     api      │                │
│  │   (Nginx)   │             │   (Django)   │                │
│  │  port 80    │             │   port 8000  │                │
│  └─────────────┘             └──────┬───────┘                │
│                                     │                         │
│  ┌─────────────┐                    ▼                         │
│  │    cron     │────────────► ┌──────────────┐               │
│  │ (same image)│              │  database    │               │
│  └─────────────┘              │ (PostgreSQL) │               │
│                               │ port 15432*  │               │
│                               └──────────────┘               │
└──────────────────────────────────────────────────────────────┘
* 15432 on host → 5432 in container (SSH tunnel / DBeaver)
Container Image / build Host port Role
frontend docker/Dockerfile.web 80 → 80 React SPA + Nginx API proxy
api docker/Dockerfile.api 18000 → 8000 Gunicorn, migrations, static
cron same as api — Scheduled management commands
database postgres:16-alpine 15432 → 5432 PostgreSQL

Prerequisites

  • Docker 20.10+
  • Docker Compose v2+
  • Ports available: 80 (UI), 18000 (direct API), 15432 (Postgres on localhost)
docker --version
docker compose version

Quick start

cd dashboard-cpsp
cp docker/.env.example .env
# Edit .env — set SECRET_KEY and DB_PASSWORD

docker compose up -d --build

Production (empty database, no demo data):

docker compose exec api python manage.py bootstrap_admin

Uses BOOTSTRAP_ADMIN_USER / BOOTSTRAP_ADMIN_PASSWORD from .env (default in docker/.env.example: admin / Pr04dm1n). Optionally set BOOTSTRAP_STAFF_USER / BOOTSTRAP_STAFF_PASSWORD to create a staff login at the same time. Then log in and create sites, kandang, and cycles in Pengaturan.

Dev / demo (Sukawarna sample cycles):

docker compose exec api python manage.py seed_demo

Logins after seed: admin / admin123, staff / staff123. Do not run seed_demo on production.

Verify

docker compose ps
docker compose logs -f

curl http://localhost/health
curl http://localhost/api/v1/health/

Open http://localhost in a browser.

Configuration files (docker/)

File Purpose
Dockerfile.web Frontend image (Vite + Nginx)
Dockerfile.api Backend image (Django + Gunicorn)
nginx.conf Nginx proxy config for frontend
entrypoint-api.sh API container startup
entrypoint-cron.sh Cron container startup
crontab Fallback schedule; runtime regenerated from DASHBOARD_PUBLISH_*
.env.example Compose env template → copy to project root .env
compose.override.local.example Optional local Postgres port override

Configuration

Compose reads variables from a root .env file. Template: docker/.env.example.

Important production values:

Variable Purpose
SECRET_KEY Django secret — use a long random string
DB_PASSWORD PostgreSQL password
CSRF_TRUSTED_ORIGINS Must include your public UI origin (e.g. https://dashboard.example.com)
CORS_ALLOWED_ORIGINS Same as above if the SPA is on a different origin
KARUNG_WEB_ADMIN_BASE_URL External karung service; default http://host.docker.internal:5000 reaches the host from containers
BOOTSTRAP_ADMIN_USER Superadmin username for bootstrap_admin (default admin)
BOOTSTRAP_ADMIN_PASSWORD Superadmin password for bootstrap_admin (required for production bootstrap)
BOOTSTRAP_STAFF_USER Optional staff username; leave empty to skip staff creation
BOOTSTRAP_STAFF_PASSWORD Staff password (required when BOOTSTRAP_STAFF_USER is set)
SITE_API_KEY Optional fixed API key for scripts (hashed at rest)

Wagtail admin is proxied at http://localhost/admin/ (through Nginx → Django).

Management

# Start / stop
docker compose start
docker compose stop
docker compose restart

# Logs
docker compose logs -f api
docker compose logs -f frontend
docker compose logs -f cron

# Django shell
docker compose exec api python manage.py shell

# Database (psql)
docker compose exec database psql -U newdashboard -d newdashboard

# From host (port 15432)
psql -h localhost -p 15432 -U newdashboard -d newdashboard

Update after code changes

git pull
docker compose down
docker compose up -d --build

Rolling update (less downtime):

docker compose build
docker compose up -d --no-deps --build api
docker compose up -d --no-deps --build cron
docker compose up -d --no-deps --build frontend

Local DBeaver on Mac

cp docker/compose.override.local.example docker-compose.override.yml

Adds 127.0.0.1:5432:5432 while keeping the server’s 15432 mapping.

Cron jobs

The cron service runs:

  • Every 10 min — sync_iot_from_api (IoT panel, real-time — not gated by publish cutoff)
  • At DASHBOARD_PUBLISH_HOUR:DASHBOARD_PUBLISH_MINUTE daily — sync_karung_from_web_admin then recompute_kpi_rollups (entrypoint renders cron from these env vars; default 17:00)

Dashboard reads hide today's KPI/counting/weight/karung data until the configured publish time WIB. IoT panel is excluded and updates live every 10 minutes.

Logs: docker compose exec cron tail -f /var/log/cron.log

Troubleshooting

API unhealthy

docker compose logs api
docker compose exec api python manage.py migrate --plan

Frontend 502 on /api

Ensure api is healthy and both services share newdashboard-network:

docker compose ps
curl http://127.0.0.1:18000/api/v1/health/

Database connection errors

Check Postgres is healthy and credentials in .env match docker-compose.yml defaults.

Port conflicts

Change mappings in docker-compose.yml, e.g. "8080:80" for frontend.

Reset database (destructive)

docker compose down -v
docker compose up -d --build
docker compose exec api python manage.py bootstrap_admin

Security notes

  • Do not commit .env with real secrets.
  • Use strong SECRET_KEY and DB_PASSWORD in production.
  • Restrict database port 15432 to localhost (already bound to 127.0.0.1).
  • Put HTTPS in front of port 80 (reverse proxy + Let's Encrypt) for public deployment.

Docker deployment guide — dashboard-cpsp