Skip to content

Docker self-hosting: full-stack container with Docker secrets support #1508

@RepairYourTech

Description

@RepairYourTech

Problem

The existing docker/ directory provides a frontend-only deployment — nginx serves the Vite build and proxies /api/ requests to an external API_UPSTREAM (defaulting to api.worldmonitor.app). This means self-hosted users still depend on the cloud API for all data, which defeats the purpose for privacy-conscious and air-gapped deployments.

PR #577 attempted to solve this by bundling local-api-server.mjs inside Docker, but was rightfully marked "Not Ready to Merge" because it mixed 28+ unrelated changes (edge caching, POST→GET migration, telegram channels, rate limiting) with only 7 Docker-related files.

Proposal

Add full-stack Docker self-hosting support using the existing local-api-server.mjs sidecar as the Node.js backend — no source code modifications required.

Architecture

┌─── Docker Container ──────────────────────────────┐
│  supervisord                                       │
│    ├── nginx (port 80)                             │
│    │     ├── / → static frontend (Vite build)      │
│    │     └── /api/ → proxy_pass localhost:46123     │
│    └── node local-api-server.mjs (port 46123)      │
│          ├── Loads api/*.js handlers dynamically    │
│          └── Cloud fallback → api.worldmonitor.app  │
└───────────────────────────────────────────────────┘

What this adds

File Purpose
Dockerfile Multi-stage build: Node 22 builder → nginx + node + supervisord runtime
docker-compose.yml Production compose with Docker secrets + env_file support
docker-entrypoint.sh Docker secrets → env var bridge + supervisord launch
supervisord.conf Process manager for nginx + node
nginx.conf Routes /api/ to local node backend instead of cloud
.dockerignore Root-level ignore for clean build context
.env.docker.example Documented env var template
DOCKER.md Self-hosting guide

Docker secrets support

Sensitive API keys (Groq, Finnhub, FRED, EIA, NASA FIRMS, etc.) can be stored as Docker secrets instead of environment variables. The entrypoint script reads /run/secrets/KEYNAME files and exports them as env vars before starting the server — no source code changes needed.

# docker-compose.yml
secrets:
  GROQ_API_KEY:
    file: ./secrets/groq_api_key.txt

services:
  worldmonitor:
    secrets:
      - GROQ_API_KEY

What this does NOT change

  • No .ts, .tsx, or .mjs files modified — only new Docker infrastructure files
  • Existing docker/ directory preserved — frontend-only users are unaffected
  • No new npm dependencies — uses existing local-api-server.mjs and api/ handlers as-is

Prior art

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions