8000 Add multi-stage Dockerfile and built-in healthcheck by avelino · Pull Request #74 · avelino/mcp · GitHub
[go: up one dir, main page]

Skip to content

Add multi-stage Dockerfile and built-in healthcheck - #74

Merged
avelino merged 1 commit into
mainfrom
avelino/distroless
Apr 13, 2026
Merged

avelino merged 1 commit into
mainfrom
avelino/distroless

Conversation

@avelino
@avelino avelino commented Apr 13, 2026
Copy link
Copy Markdown
Owner

The Dockerfile required a pre-built binary and the compose file referenced a nonexistent Dockerfile.dev. The health check ran mcp serve --help which always exits 0 regardless of server state.

Replace with a multi-stage build (rust:alpine to scratch) that compiles from source and produces an 11.8MB image. Add mcp healthcheck [url] subcommand so scratch images can probe /health without external tools.

Fixes: #65
Fixes: #66
Fixes: #73

The Dockerfile required a pre-built binary and the compose file
referenced a nonexistent Dockerfile.dev. The health check ran
`mcp serve --help` which always exits 0 regardless of server state.

Replace with a multi-stage build (rust:alpine to scratch) that compiles
from source and produces an 11.8MB image. Add `mcp healthcheck [url]`
subcommand so scratch images can probe /health without external tools.

Fixes: #65
Fixes: #66
Fixes: #73

Signed-off-by: Avelino <31996+avelino@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 13, 2026 01:46
@avelino
avelino merged commit 338b6cb into main Apr 13, 2026
4 checks passed
@avelino
avelino deleted the avelino/distroless branch April 13, 2026 01:48
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves container usability by making the Docker image build reproducible from source and adding a real runtime health probe suitable for minimal (scratch/distroless) images.

Changes:

  • Replaces the single-stage Dockerfile that required a prebuilt binary with a multi-stage build producing a minimal scratch runtime image.
  • Adds a new mcp healthcheck [url] CLI subcommand that probes GET /health and returns an appropriate exit code.
  • Fixes docker-compose.yml to reference the correct Dockerfile and to use the new healthcheck command.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
src/main.rs Adds mcp healthcheck [url] subcommand and usage entry for container health probing.
Dockerfile Introduces multi-stage Rust build on Alpine and a scratch runtime stage.
docker-compose.yml Switches build to Dockerfile and updates healthcheck to call mcp healthcheck.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/main.rs
Comment on lines +94 to +101
// Built-in HTTP health probe for container health checks (scratch/distroless
// images have no curl/wget). Exits 0 if the endpoint returns 2xx, 1 otherwise.
if args[0] == "healthcheck" {
let url = args
.get(1)
.map(|s| s.as_str())
.unwrap_or("http://localhost:8080/health");
let client = reqwest::Client::builder()
Copilot AI Apr 13, 2026
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

healthcheck runs after config::load_config()/reserved-name validation. In scratch/distroless images dirs::home_dir() can fail (no HOME or /etc/passwd), which would make mcp healthcheck exit 1 even if the HTTP server is healthy. Consider handling healthcheck (and --help) before loading config, and also add healthcheck to the reserved command-name list so server aliases can’t shadow this new subcommand silently.

Copilot uses AI. Check for mistakes.
Comment thread Dockerfile
COPY --from=builder /app/target/release/mcp /usr/local/bin/mcp

EXPOSE 8080
ENTRYPOINT ["mcp"]
Copilot AI Apr 13, 2026
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a scratch runtime, relying on ENTRYPOINT ["mcp"] can fail because PATH is typically unset. Use an absolute entrypoint (e.g. /usr/local/bin/mcp) or set ENV PATH=/usr/local/bin so both the entrypoint and docker-compose healthcheck can find the binary.

Suggested change
ENTRYPOINT ["mcp"]
ENTRYPOINT ["/usr/local/bin/mcp"]

Copilot uses AI. Check for mistakes.
Comment thread Dockerfile
Comment on lines +11 to +16
cargo build --release && \
rm -rf src

# Build the real binary
COPY src/ src/
RUN touch src/main.rs && cargo build --release
Copilot AI Apr 13, 2026
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build stage uses cargo build --release without --locked. That allows dependency resolution to drift from Cargo.lock during image builds, reducing reproducibility. Use --locked (at least for the final build) to ensure the image is built from the checked-in lockfile.

Suggested change
cargo build --release && \
rm -rf src
# Build the real binary
COPY src/ src/
RUN touch src/main.rs && cargo build --release
cargo build --release --locked && \
rm -rf src
# Build the real binary
COPY src/ src/
RUN touch src/main.rs && cargo build --release --locked

Copilot uses AI. Check for mistakes.
Comment thread Dockerfile
# --- Build stage (Alpine = native musl, no cross-compile wrapper) ---
FROM rust:alpine AS builder

RUN apk add --no-cache musl-dev
Copilot AI Apr 13, 2026
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The runtime stage copies /etc/ssl/certs/ca-certificates.crt from the builder, but the Dockerfile doesn’t explicitly install/update CA certificates in the builder. To avoid depending on base-image defaults, install ca-certificates (and run the update step if needed) in the builder so this copy is guaranteed to succeed and the cert bundle is current.

Suggested change
RUN apk add --no-cache musl-dev
RUN apk add --no-cache musl-dev ca-certificates && \
update-ca-certificates

Copilot uses AI. Check for mistakes.
Comment thread docker-compose.yml
restart: unless-stopped
healthcheck:
test: ["CMD", "mcp", "serve", "--help"]
test: ["CMD", "mcp", "healthcheck"]
Copilot AI Apr 13, 2026
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

healthcheck runs mcp via PATH. If the image moves to scratch without setting PATH (or uses an absolute ENTRYPOINT only), this healthcheck can fail with “executable not found”. Consider calling /usr/local/bin/mcp here or ensure the image sets PATH=/usr/local/bin.

Suggested change
test: ["CMD", "mcp", "healthcheck"]
test: ["CMD", "/usr/local/bin/mcp", "healthcheck"]

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants

0