name: dashboard-cpsp services: database: image: postgres:16-alpine container_name: dashboard-cpsp-database restart: unless-stopped environment: POSTGRES_USER: ${DB_USER:-dashboard} POSTGRES_PASSWORD: ${DB_PASSWORD:-Ket0pr4k} POSTGRES_DB: ${DB_NAME:-dashboard} PGDATA: /var/lib/postgresql/data/pgdata volumes: - db-data:/var/lib/postgresql/data networks: - dashboard-cpsp-network healthcheck: test: [ "CMD-SHELL", "pg_isready -U ${DB_USER:-dashboard} -d ${DB_NAME:-dashboard}", ] interval: 10s timeout: 5s retries: 5 start_period: 10s # Server: SSH tunnel / DBeaver via localhost:15432 (avoids host Postgres on 5432). # Mac dev: add docker-compose.override.yml from docker/compose.override.local.example for :5432. ports: - "127.0.0.1:15432:5432" api: image: dashboard-cpsp-api build: context: . dockerfile: docker/Dockerfile.api container_name: dashboard-cpsp-api restart: unless-stopped ports: - "127.0.0.1:18000:8000" environment: DEBUG: ${DEBUG:-false} SECRET_KEY: ${SECRET_KEY:-test-secret-key} ALLOWED_HOSTS: ${ALLOWED_HOSTS:-localhost,127.0.0.1,api,frontend,192.168.192.106} CSRF_TRUSTED_ORIGINS: ${CSRF_TRUSTED_ORIGINS:-http://localhost:5002,http://127.0.0.1:5002,http://192.168.192.106:5002} CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS:-http://localhost:5002,http://127.0.0.1:5002,http://192.168.192.106:5002} CORS_ALLOW_CREDENTIALS: "true" DB_ENGINE: django.db.backends.postgresql DB_NAME: ${DB_NAME:-dashboard} DB_USER: ${DB_USER:-dashboard} DB_PASSWORD: ${DB_PASSWORD:-Ket0pr4k} DB_HOST: database DB_PORT: "5432" KARUNG_WEB_ADMIN_BASE_URL: ${KARUNG_WEB_ADMIN_BASE_URL:-http://host.docker.internal:5000} KARUNG_WEB_ADMIN_TIMEOUT_SECONDS: ${KARUNG_WEB_ADMIN_TIMEOUT_SECONDS:-30} KARUNG_WEB_ADMIN_SYNC_ENABLED: ${KARUNG_WEB_ADMIN_SYNC_ENABLED:-false} DASHBOARD_PUBLISH_HOUR: ${DASHBOARD_PUBLISH_HOUR:-17} DASHBOARD_PUBLISH_MINUTE: ${DASHBOARD_PUBLISH_MINUTE:-0} IOT_SYNC_ENABLED: ${IOT_SYNC_ENABLED:-true} IOT_API_BASE_URL: ${IOT_API_BASE_URL:-https://dashboard.cpsp.id/api/iot/flocks} IOT_FLOCK_ID_MAP: ${IOT_FLOCK_ID_MAP:-{}} IOT_SYNC_LOOKBACK_MINUTES: ${IOT_SYNC_LOOKBACK_MINUTES:-20} IOT_SYNC_MAX_PAGES: ${IOT_SYNC_MAX_PAGES:-10} BOOTSTRAP_API_KEY: ${BOOTSTRAP_API_KEY:-test-api-key} BOOTSTRAP_ADMIN_USER: ${BOOTSTRAP_ADMIN_USER:-admin} BOOTSTRAP_ADMIN_PASSWORD: ${BOOTSTRAP_ADMIN_PASSWORD:-Pr04dm1n} BOOTSTRAP_STAFF_USER: ${BOOTSTRAP_STAFF_USER:-skw} BOOTSTRAP_STAFF_PASSWORD: ${BOOTSTRAP_STAFF_PASSWORD:-skw123} extra_hosts: - "host.docker.internal:host-gateway" volumes: - api-media:/app/media depends_on: database: condition: service_healthy networks: - dashboard-cpsp-network healthcheck: test: [ "CMD", "python", "-c", "import urllib.request; r=urllib.request.urlopen('http://127.0.0.1:8000/api/v1/health/'); exit(0 if r.status == 200 else 1)", ] interval: 30s timeout: 5s retries: 3 start_period: 60s cron: image: dashboard-cpsp-cron build: context: . dockerfile: docker/Dockerfile.api container_name: dashboard-cpsp-cron restart: unless-stopped entrypoint: ["/app/entrypoint-cron.sh"] environment: DEBUG: ${DEBUG:-false} SECRET_KEY: ${SECRET_KEY:-test-secret-key} ALLOWED_HOSTS: ${ALLOWED_HOSTS:-localhost,127.0.0.1,api,frontend} DB_ENGINE: django.db.backends.postgresql DB_NAME: ${DB_NAME:-dashboard} DB_USER: ${DB_USER:-dashboard} DB_PASSWORD: ${DB_PASSWORD:-Ket0pr4k} DB_HOST: database DB_PORT: "5432" KARUNG_WEB_ADMIN_BASE_URL: ${KARUNG_WEB_ADMIN_BASE_URL:-http://host.docker.internal:5000} KARUNG_WEB_ADMIN_TIMEOUT_SECONDS: ${KARUNG_WEB_ADMIN_TIMEOUT_SECONDS:-30} KARUNG_WEB_ADMIN_SYNC_ENABLED: ${KARUNG_WEB_ADMIN_SYNC_ENABLED:-false} DASHBOARD_PUBLISH_HOUR: ${DASHBOARD_PUBLISH_HOUR:-9} DASHBOARD_PUBLISH_MINUTE: ${DASHBOARD_PUBLISH_MINUTE:-30} IOT_SYNC_ENABLED: ${IOT_SYNC_ENABLED:-true} IOT_API_BASE_URL: ${IOT_API_BASE_URL:-https://dashboard.cpsp.id/api/iot/flocks} IOT_FLOCK_ID_MAP: ${IOT_FLOCK_ID_MAP:-{}} IOT_SYNC_LOOKBACK_MINUTES: ${IOT_SYNC_LOOKBACK_MINUTES:-20} IOT_SYNC_MAX_PAGES: ${IOT_SYNC_MAX_PAGES:-10} extra_hosts: - "host.docker.internal:host-gateway" volumes: - api-media:/app/media depends_on: api: condition: service_healthy networks: - dashboard-cpsp-network frontend: image: dashboard-cpsp-frontend build: context: . dockerfile: docker/Dockerfile.web container_name: dashboard-cpsp-frontend restart: unless-stopped ports: - "5002:80" depends_on: api: condition: service_healthy networks: - dashboard-cpsp-network healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:80/health"] interval: 30s timeout: 3s retries: 3 start_period: 10s networks: dashboard-cpsp-network: driver: bridge volumes: db-data: driver: local api-media: driver: local