Skip to content

feat: add Dockerfile + .dockerignore - #5

Merged
fengyat merged 1 commit into
mainfrom
feat/add-dockerfile
May 25, 2026
Merged

feat: add Dockerfile + .dockerignore#5
fengyat merged 1 commit into
mainfrom
feat/add-dockerfile

Conversation

@fengyat

@fengyat fengyat commented May 25, 2026

Copy link
Copy Markdown
Member

Why

Glama indexes MCP servers by spawning each one in a Firecracker microVM, running build, and then doing MCP protocol introspection. They prefer a hand-authored Dockerfile in the repo; otherwise they fall back to an AI-inferred one which can fail in non-obvious ways. Our glama submission has been pending for hours — adding a proper Dockerfile should unblock it (and by extension our punkpeye/awesome-mcp-servers PR #6878, which is gated on the glama badge).

What's in the Dockerfile

Two-stage build:

  1. builder (node:20-alpine): copy manifest + source, npm install, npm run build (tsup → dist/index.js), then npm prune --omit=dev
  2. runtime (node:20-alpine): copy dist/, pruned node_modules, and package.json. Run as node user. ENTRYPOINT ["node", "/app/dist/index.js"]

Final image: 224 MB (typical alpine + node_modules baseline).

Local verification

docker build -t orcarouter-mcp:test .
# → succeeds

npx @modelcontextprotocol/inspector --cli docker run -i --rm orcarouter-mcp:test --method tools/list
# → 4 tools listed, orcarouter_chat.max_tokens.default = 10000

npx @modelcontextprotocol/inspector --cli docker run -i --rm orcarouter-mcp:test --method tools/call --tool-name orcarouter_models_list
# → isError: false, Found 159 models

Container behavior is identical to bare node dist/index.js — same tools, same defaults, same no API key needed for catalog semantics.

.dockerignore

Excludes from the build context: .git, .github, .claude, node_modules, dist, test, examples, assets, locale READMEs, bun.lock (we use npm in the image), vitest.config.ts, etc. Keeps the build fast and the image clean.

Out of scope

  • Publishing to a container registry (Docker Hub / ghcr.io) — can be a follow-up. For now, Glama scanner builds its own image from this Dockerfile, which is enough for indexing.
  • Compose file — single-container service doesn't need one.

Test plan

  • docker build succeeds locally
  • Container responds to MCP tools/list and tools/call
  • No-key catalog tools work inside the container
  • After merge, re-verify glama scanner progresses past the build stage (will check 24h after merge)

…er deploys

Two-stage Dockerfile (node:20-alpine) that builds the TypeScript source
with tsup, prunes devDependencies, and copies the result into a lean
runtime image. Final container runs `node /app/dist/index.js`, speaking
MCP over stdio.

Local verification with MCP Inspector CLI:
  - docker build .                              succeeds (image: 224 MB)
  - tools/list                                  returns 4 tools
  - orcarouter_chat.max_tokens.default          = 10000 (matches v1.1.3)
  - orcarouter_models_list (no API key)         returns 159 models

Primary motivation: Glama indexes by spawning each server in a
Firecracker microVM and running MCP introspection. With a hand-authored
Dockerfile in the repo, Glama uses ours instead of inferring one via
their AI heuristic — faster scan, fewer surprises.

Bonus: any user who prefers container deploys can now
`docker run -i --rm <image> --rm -e ORCAROUTER_API_KEY=...` instead of
npx.

.dockerignore keeps the build context lean (no node_modules / dist /
test / examples / READMEs / locale files / vitest config in the image
layers).
@fengyat

fengyat commented May 25, 2026

Copy link
Copy Markdown
Member Author

@codex

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@fengyat
fengyat merged commit e7e7e76 into main May 25, 2026
1 check passed
fengyat added a commit that referenced this pull request May 26, 2026
`npm ci` requires a package-lock.json. This repo uses bun as its
primary package manager and only commits bun.lock, so the v1.1.4 tag
push triggered a CI failure at the Install dependencies step:

    npm error The `npm ci` command can only install with an existing
    package-lock.json or npm-shrinkwrap.json

PR #3 originally chose `npm ci` from the official MCP Registry docs
example — that example assumes an npm-managed project. Our Dockerfile
(merged in #5) already uses `npm install --no-audit --no-fund` against
the same package.json with no issues; this commit aligns the publish
workflow with that pattern.

We accept the trade-off of non-pinned transitive deps in CI: deps are
pinned to caret ranges in package.json that have been stable across
releases, the build is bundled by tsup so transitive shape doesn't
leak into the published artifact, and tag-gated runs are infrequent
enough that drift detection is moot.

After this merges, the existing v1.1.4 tag needs to be re-pointed at
the new commit (delete + recreate) to retrigger publish — there is no
v1.1.4 on npm or MCP Registry yet, since the failed run aborted before
either publish step.

Co-authored-by: fengyat <fengya.tian@continuum01.ai>
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