diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..493b503 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +node_modules +.git +.env +.gev-cache +.gev-logs +dist diff --git a/CHANGELOG.md b/CHANGELOG.md index 21544fa..b012fde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ of current runtime behavior, see [`docs/CURRENT-STATE.md`](docs/CURRENT-STATE.md ## [Unreleased] +### Added + +- **Docker install path.** `docker compose up` builds the pinned Node image and + serves the app on `http://localhost:4173` with no local Node install. The repo + is bind-mounted and the container runs as the host user, so keys saved from + Provider Settings, `.gev-cache`, and `.gev-logs` persist on the host exactly + as they do under `npm run dev`. + ### Fixed - Mapped-site outages show their scheduled retry countdown and distinguish diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b4706ff --- /dev/null +++ b/Dockerfile @@ -0,0 +1,28 @@ +# syntax=docker/dockerfile:1 +# +# The dev server is the whole app: Vite serves the client AND runs the API +# proxies (ADS-B, AIS, Overpass, OpenAI Realtime, ...) as middleware, so there +# is nothing else to containerise. See compose.yaml for the usual entry point. +FROM node:24-slim + +# Puppeteer is only used by the QA scripts; skip its ~150MB Chromium download. +ENV PUPPETEER_SKIP_DOWNLOAD=1 +WORKDIR /app + +COPY package.json package-lock.json ./ +RUN npm ci +# compose runs the container as the host user so bind-mounted files stay +# yours, but node_modules is baked in as root. Vite only needs to write its +# dep-optimizer cache, so open up those two directories rather than chowning +# a few hundred MB to a UID we cannot know at build time. +RUN mkdir -p node_modules/.vite && chmod 777 node_modules node_modules/.vite + +COPY . . + +# Bind to all interfaces, otherwise the published port hits nothing. Vite also +# relaxes allowedHosts when HOST is 0.0.0.0, which is what lets the browser +# reach it as "localhost". +ENV HOST=0.0.0.0 +ENV PORT=4173 +EXPOSE 4173 +CMD ["npm", "run", "dev"] diff --git a/README.md b/README.md index 86f69c5..05ead16 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,30 @@ See [docs/PERFORMANCE.md](docs/PERFORMANCE.md). **macOS shortcut:** `./scripts/dev-fresh.sh` clears the Vite cache and pulls any configured keys straight from the Keychain. It starts keyless too. +### Path 3 — Docker + +No Node install needed; the container publishes the same dev server. + +```bash +git clone https://github.com/bilawalsidhu/gods-eye-view.git +cd gods-eye-view +docker compose up +``` + +Open **`http://localhost:4173`** as above. The repo is bind-mounted, so keys you +paste into Provider Settings persist in your host `.env` and source edits still +hot-reload. The container binds `0.0.0.0` *inside* the container, but the port +is published to `127.0.0.1` only, so the default matches the native one: nobody +else can reach your server. Widening that mapping puts you under +[Sharing an instance](#-sharing-an-instance) — keys and all. + +`node_modules` deliberately stays inside the image, so it survives in an +anonymous volume across restarts: after a `git pull` that changes dependencies, +recreate it with `docker compose down -v && docker compose up --build`. The +image also skips Puppeteer's Chromium download, which keeps it small but leaves +`npm run test:track` to the host — `npm run build` and `npm test` run fine in +the container. + ### Then power it up — in the app, not in a file Keys are upgrades, not prerequisites. When you want one, click the **POWER UP** diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..7826bf3 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,21 @@ +services: + gods-eye-view: + build: . + # Everything the app writes (.env with your keys, .gev-cache, .gev-logs) + # lands in the bind-mounted repo, so run as you, not root. UID/GID are + # unset on Docker Desktop, where the 1000 fallback is ignored anyway. + user: "${UID:-1000}:${GID:-1000}" + ports: + # Publish to loopback only. Docker's default ("4173:4173") would bind + # every host interface, which quietly turns the LAN warning in the README + # into the default: this server brokers whatever provider keys you have + # configured to anyone who can reach it. Widen this deliberately, not by + # accident. + - "127.0.0.1:4173:4173" + volumes: + # Bind the source so edits hot-reload and so keys pasted into the setup + # UI land in the .env on your host instead of vanishing with the + # container. node_modules stays in the image: sharp and friends are + # compiled for Linux and must not be shadowed by a host install. + - .:/app + - /app/node_modules