Skip to content

build(railway): split Dockerfiles — web at root, MCP at Dockerfile.mcp#39

Merged
hwesterb merged 1 commit intomainfrom
fix/railway-web-dockerfile
Apr 18, 2026
Merged

build(railway): split Dockerfiles — web at root, MCP at Dockerfile.mcp#39
hwesterb merged 1 commit intomainfrom
fix/railway-web-dockerfile

Conversation

@hwesterb
Copy link
Copy Markdown
Member

Problem

After #37 merged, Railway's web deploy started failing. Root cause: Railway auto-detects a canonical-name `Dockerfile` at repo root and uses it for the build, overriding `"builder": "NIXPACKS"` in railway.json. Per Railway's own docs, there is no override that forces Nixpacks when a root Dockerfile is present. Our MCP Dockerfile runs `sema mcp` on stdio, which is wrong for the web deploy.

Previous successful deploy (0.2.3 via Nixpacks) is still serving traffic at semahash.org — Railway kept the last good deploy running — so nothing is down. This PR is the forward fix.

Fix: two Dockerfiles, each for its own consumer

  • `Dockerfile` (root, canonical) — new multi-stage build. Node 20 compiles the React frontend; Python 3.12 installs the backend and copies the built frontend into `src/sema/server/static/`. CMD runs `sema serve --host 0.0.0.0 --port ${PORT:-3000}`. This is what Railway auto-detects.
  • `Dockerfile.mcp` — the stdio MCP container from build: add Dockerfile for Glama check + containerized use #37, unchanged. Submitted to Glama's admin form; the non-canonical name keeps Railway from picking it up.
  • `.dockerignore` — trims the build context.
  • `railway.json` — Nixpacks-specific `build` block removed since Railway will use the Dockerfile. Healthcheck + restart policy kept.
  • `nixpacks.toml` — kept as a breadcrumb for now; can retire in a follow-up once the Docker path is proven.

Test plan

  • pytest green locally (all hooks pass)
  • Railway deploy succeeds on merge (cannot test without a Railway preview — will watch the deploy)
  • semahash.org continues serving 0.2.3 content (API + frontend) after the deploy completes
  • Glama: when the admin page becomes available for `sema`, paste contents of `Dockerfile.mcp` into their form

If deploy fails

Fallback: close this PR, revert to Nixpacks by putting the old `railway.json` back. Current site stays up either way because Railway doesn't roll back the running deploy on a failed redeploy.

Problem: Railway's web deploy failed after PR #37 merged because Railway
auto-detects a canonical-name `Dockerfile` at repo root and uses it for
the build, overriding the explicit `"builder": "NIXPACKS"` in railway.json
(confirmed via Railway's own docs — there is no override that forces
Nixpacks when a root Dockerfile is present). The MCP Dockerfile runs
`sema mcp` on stdio, which isn't the web deploy.

Fix: give each consumer its own Dockerfile.

- `Dockerfile` (root, canonical) — multi-stage build that compiles the
  React frontend (Node 20) and runs the FastAPI server on $PORT via
  `sema serve`. This is what Railway auto-detects and consumes. Mirrors
  what the previous Nixpacks buildCommand + startCommand did, but in a
  single coherent artifact and without the "rebuild at startup to avoid
  COPY overwrite" workaround (Docker layers make that unnecessary).
- `Dockerfile.mcp` (non-canonical name) — the original stdio MCP server
  container, unchanged. This is the artifact submitted to Glama's
  admin form; the non-canonical name keeps Railway from touching it.
- `.dockerignore` — trims the build context (git, venvs, experiments,
  pre-built artifacts).
- `railway.json` — drops the Nixpacks-specific `build` block (no longer
  used since Railway will pick up the Dockerfile). Keeps healthcheck +
  restart policy.
- `nixpacks.toml` — kept for now as a breadcrumb of the previous build
  recipe; can be removed later once the Docker path is proven.

Previous successful deploy (0.2.3 via Nixpacks) is still serving traffic
at semahash.org, so nothing is down. This PR is the forward fix so the
next merge to main redeploys cleanly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hwesterb hwesterb merged commit 83412d5 into main Apr 18, 2026
5 checks passed
@hwesterb hwesterb deleted the fix/railway-web-dockerfile branch April 18, 2026 20:44
hwesterb added a commit that referenced this pull request Apr 18, 2026
Correcting the direction of #39. The root `Dockerfile` is now back to
the MCP stdio server (its original canonical-path content, the artifact
Glama fetches). The multi-stage web build lives at `Dockerfile.web`, and
Railway is configured via the `RAILWAY_DOCKERFILE_PATH` environment
variable to build from it instead of auto-detecting the root Dockerfile.

Also folds in the missing-include fix from PR #40: `.claude-plugin/`
and `skills/` must be COPY'd before `pip install` because hatchling's
`force-include` demands they exist at build time.

Env var set on Railway separately via `railway variable set`.

Effective layout after this PR:

- `Dockerfile`       MCP stdio server (unchanged from #37)       → Glama
- `Dockerfile.web`   Multi-stage web build                        → Railway
- `.dockerignore`    Trims build context                          → both
- `railway.json`     Healthcheck + restart policy only            → Railway

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant