Files
dashboard-cpsp/DOCKER.md
T
2026-10-01 13:23:45 +07:00

220 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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)
```bash
docker --version
docker compose version
```
## Quick start
```bash
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):
```bash
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):
```bash
docker compose exec api python manage.py seed_demo
```
Logins after seed: `admin` / `admin123`, `staff` / `staff123`. Do **not** run `seed_demo` on production.
### Verify
```bash
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
```bash
# 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
```bash
git pull
docker compose down
docker compose up -d --build
```
Rolling update (less downtime):
```bash
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
```bash
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**
```bash
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`:
```bash
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)
```bash
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