Package the area editor + Godot 4.7.2 as a Docker container #65

Merged
Nimby merged 1 commit from task/64-editor-container into main 2026-10-05 01:40:43 -04:00
Collaborator

Closes #64

Run on a headless server (optibcc) with cd tools/mapgen/web_editor/docker && docker compose up -d --build, then open http://<server>:8765/ on the LAN.

Image (docker/Dockerfile)

  • debian:bookworm-slim + Python 3 + the official Godot 4.7.2 Linux build, with SHA-512 pinned from the release's SHA512-SUMS.txt. Picks amd64 or arm64 automatically.
  • Xvfb + Mesa (llvmpipe) so Render preview works with no GPU or display. The X11/GL package list is what a real render actually loads, measured with LD_DEBUG, not guessed.
  • tini as init, a healthcheck on /api/health, and --audio-driver Dummy for renders.

Runtime (entrypoint.sh, compose.yaml)

  • The checkout containing compose.yaml is bind-mounted at /repo. Editor code and area JSON both come from it, so edits land in your clone for git diff / commit / push, and a git pull + docker compose restart updates the editor. No credentials in the container.
  • Runs as UID/GID 1000 by default (overridable via .env), so nothing written into the checkout is root-owned.
  • Imports the project on startup (retrying once, per the known first-import crash), so a fresh clone without .godot/ renders. Core dumps are disabled so a crash can't drop a large file into the checkout.

Small changes to the editor

  • server.py --host (default stays 127.0.0.1; the container passes 0.0.0.0).
  • render_preview.py honors RENDER_EXTRA_GODOT_ARGS.
  • Saved descriptors keep number arrays on one line, so moving an item is a one-line diff. Previously the first save reformatted the whole file. _sample_room.json is normalized to this format.

Verified in the sandbox (no Docker available there, so each piece was checked separately)

  • Replayed the Dockerfile's x86_64 download: checksum OK, and the zip contains exactly Godot_v4.7.2-stable_linux.x86_64 (mode 755). All apt package names exist in bookworm.
  • Ran the real entrypoint.sh against a fresh clone (no .godot/) with the image's env, godot on PATH, and dummy audio: the import ran, the server came up on 0.0.0.0, and /api/health plus a /api/render PNG worked via the container's non-loopback IP. The rendered frame is correct.
  • After import + render, the clone's git status was clean; an editor save showed up as a normal modified file.

Not yet verified: an actual docker build / docker compose up on x86_64. The first build on optibcc is the real test.

🤖 Generated with Claude Code

Closes #64 Run on a headless server (optibcc) with `cd tools/mapgen/web_editor/docker && docker compose up -d --build`, then open `http://<server>:8765/` on the LAN. **Image** (`docker/Dockerfile`) - `debian:bookworm-slim` + Python 3 + the official Godot 4.7.2 Linux build, with SHA-512 pinned from the release's `SHA512-SUMS.txt`. Picks amd64 or arm64 automatically. - Xvfb + Mesa (llvmpipe) so Render preview works with no GPU or display. The X11/GL package list is what a real render actually loads, measured with `LD_DEBUG`, not guessed. - `tini` as init, a healthcheck on `/api/health`, and `--audio-driver Dummy` for renders. **Runtime** (`entrypoint.sh`, `compose.yaml`) - The checkout containing `compose.yaml` is bind-mounted at `/repo`. Editor code and area JSON both come from it, so edits land in your clone for `git diff` / commit / push, and a `git pull` + `docker compose restart` updates the editor. No credentials in the container. - Runs as UID/GID 1000 by default (overridable via `.env`), so nothing written into the checkout is root-owned. - Imports the project on startup (retrying once, per the known first-import crash), so a fresh clone without `.godot/` renders. Core dumps are disabled so a crash can't drop a large file into the checkout. **Small changes to the editor** - `server.py --host` (default stays `127.0.0.1`; the container passes `0.0.0.0`). - `render_preview.py` honors `RENDER_EXTRA_GODOT_ARGS`. - Saved descriptors keep number arrays on one line, so moving an item is a one-line diff. Previously the first save reformatted the whole file. `_sample_room.json` is normalized to this format. **Verified in the sandbox** (no Docker available there, so each piece was checked separately) - Replayed the Dockerfile's x86_64 download: checksum OK, and the zip contains exactly `Godot_v4.7.2-stable_linux.x86_64` (mode 755). All apt package names exist in bookworm. - Ran the real `entrypoint.sh` against a **fresh clone** (no `.godot/`) with the image's env, `godot` on PATH, and dummy audio: the import ran, the server came up on `0.0.0.0`, and `/api/health` plus a `/api/render` PNG worked via the container's non-loopback IP. The rendered frame is correct. - After import + render, the clone's `git status` was clean; an editor save showed up as a normal modified file. **Not yet verified:** an actual `docker build` / `docker compose up` on x86_64. The first build on optibcc is the real test. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Lets the editor run on a headless x86_64 (or arm64) server with
docker compose, with Render preview working via Xvfb + Mesa llvmpipe.
The image holds only Python, a checksum-verified official Godot build,
and the X11/GL libraries a render actually loads (measured with
LD_DEBUG). The editor code and data come from the bind-mounted checkout,
which is imported on startup so a fresh clone renders correctly; edits
land in that checkout for the user to review and commit. Runs as the
host user so nothing it writes is root-owned.

server.py gains --host (default stays localhost); render_preview.py
reads RENDER_EXTRA_GODOT_ARGS so the image can force the dummy audio
driver. Saved descriptors keep number arrays on one line, so moving an
item is a one-line diff; the sample area is normalized to that format.

Closes #64

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nimby merged commit 199fc9468b into main 2026-10-05 01:40:43 -04:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
scruffydude/project-awry!65
No description provided.