docs(docker): mark the deployment spec implemented

Status implemented, verification intro rewritten, and a verification record of the final checks (dotnet build/test, both image variants, offline probes of uid, /proc environ and the diagnostics socket, playwright-mcp --version offline, headless Chromium as app, docker compose config, compose start with a fake token -> 401 -> exit 1). Open question 2 (Playwright compose default) marked resolved.
This commit is contained in:
EugeneTes
2026-09-27 12:22:06 +02:00
parent 92c881377b
commit b9a95a57c8

View File

@@ -1,6 +1,6 @@
# Docker deployment (Coolify) — design
Date: 2026-09-26. Status: draft.
Date: 2026-09-26. Status: implemented (plan: docs/superpowers/plans/2026-09-26-docker-deployment.md).
Depends on: `2026-09-26-process-environment-hook-design.md` (the secrets below stay out of agent-spawned processes),
`2026-09-26-scheduler-design.md` §7 (the default time zone).
@@ -215,7 +215,12 @@ the `claude` volume also works but is not the documented path.
## Verification
No unit tests (nothing in C# changes). Manual checklist in the implementation plan:
One unit test (`PlaywrightPresetTests.Dockerfile_version_matches_DefaultPackage`); no C# behaviour changes. Checked
during implementation without a real bot: both image variants build; bridge guard, `claude --version`, the agent
tools, uid 1654, `/data` ownership; root-owned PID 1 whose `/proc/1/environ` and the bot's are unreadable to `app`;
no `dotnet-diagnostic-*` socket; `playwright-mcp --version` offline and a headless Chromium launch as `app`;
`docker compose config`; host startup log and the `401` → exit 1 path. The rest of this list needs a real bot and
stays a manual checklist:
1. `docker compose build` succeeds with `INSTALL_PLAYWRIGHT=false` and `true`; the bridge guard and `claude --version` pass.
2. `docker compose up` with a real bot: allowed user gets answers; `/claude-code-login` then `/claude-code-doctor`
@@ -227,12 +232,35 @@ No unit tests (nothing in C# changes). Manual checklist in the implementation pl
4. `docker compose down && docker compose up -d --build`: previous chat resumes, no re-login needed, workspace files remain.
5. Setting `ANTHROPIC_API_KEY` in compose makes the provider refuse with its documented error (then remove it).
Verification record (2026-09-27, Docker Desktop 29 on Windows 11, Linux containers):
- `dotnet build`: 0 warnings, 0 errors. `dotnet test`: all green except the three Windows-only baseline failures in
`Volcanic.AgenticCore.Tests`. Changing the Dockerfile's `PLAYWRIGHT_MCP_VERSION` to `0.0.81` makes
`Dockerfile_version_matches_DefaultPackage` fail (`Expected "0.0.82", Actual "0.0.81"`).
- `docker build --build-arg INSTALL_PLAYWRIGHT=false` and `=true` both succeed. `claude --version` → `2.1.283 (Claude
Code)`; bridge `runtimeconfig.json` present; `DOTNET_EnableDiagnostics=0`; `git`, `rg`, `python3`, `node` (v24.21.0),
`npx`, `jq`, `setpriv` on `PATH`; `/data/{workspaces,agent,claude}` owned by `app`. With Playwright,
`playwright-mcp --version` → `Version 0.0.82` with `--network none`, Chromium under `/opt/ms-playwright`, and a
headless Chromium launch as `app` renders a page.
- Running host, `--init --network none`: PID 1 `docker-init` as root, the bot's `dotnet` as uid/gid 1654 with no
effective capabilities; `/proc/1/environ` and the bot's `environ` are `Permission denied` for `app` (the bot's also
for a root `docker exec`, since the host is not dumpable); no `dotnet-diagnostic-*` socket. The log shows
`Host process hardened: not dumpable`, `Process environment: 15 deny rules, allow: none`, the MCP line
(`disabled` / `enabled (headless, chromium)`), `Speech to text`, `Using Claude Code at /usr/bin/claude, model
claude-code/claude-opus-5-5`, `Scheduler`, `Default time zone: UTC`, `Allowed users: 1. Workspaces under
/data/workspaces`, then `Telegram unreachable` backoff.
- `docker compose config`: with a minimal `.env` (`INSTALL_PLAYWRIGHT=false`), `PLAYWRIGHT_ENABLED` follows it to
`"false"`; with `.env.example`'s defaults it is `"true"`; `--no-sandbox`, `playwright-mcp`, `init: true`,
`shm_size`, three named volumes, no ports.
- `docker compose up -d --build` with `TELEGRAM_BOT_TOKEN=123:fake`: same startup lines, then `Telegram rejected the bot
token (401 Unauthorized)`, exit 1, and a visible `restart: unless-stopped` loop; no other warnings.
## Open questions
1. Persist `HOME` too? `~/.gitconfig`, `~/.ssh`, `gh` auth and the npm/npx cache are lost on redeploy with this
design. A fourth volume at `/home/app` would keep them; left out until there is a need.
2. Playwright default: compose builds it in (`true`) on the assumption that the MCP spec ships; flip the compose
default to `false` if that spec lands later. (Sandboxing and which binary is launched are settled above.)
2. ~~Playwright default~~: resolved. The MCP spec shipped first, so compose keeps building it in (`true`).
(Sandboxing and which binary is launched are settled above.)
3. `CLAUDE_CODE_VERSION=2.1` tracks the newest 2.1.x at build time. Pin an exact, doctor-verified version instead,
at the cost of manual bumps?
4. Should the agent get a .NET SDK in the image (`INSTALL_DOTNET_SDK` build arg, +~700 MB) so it can build .NET