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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user