Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions modelcontextprotocol/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,31 @@ FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS builder
# Set environment variables for build
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1
PIP_NO_CACHE_DIR=1 \
UV_COMPILE_BYTECODE=1 \
UV_LINK_MODE=copy

# Install the project into `/app`
WORKDIR /app

ADD . /app
# Copy only dependency files first (better caching)
COPY pyproject.toml uv.lock ./
COPY version.py ./
COPY README.md ./

# Create a virtual environment and install dependencies
RUN python -m venv /app/.venv
ENV PATH="/app/.venv/bin:$PATH"
RUN uv sync --no-cache-dir --no-dev --python /app/.venv/bin/python

# Copy the rest of the application
COPY . /app

FROM python:3.12-slim-bookworm AS runtime

RUN groupadd -r appuser && useradd -r -g appuser -m -d /home/appuser appuser
# Create non-root user with specific UID/GID for better security
RUN groupadd -r -g 1001 appuser && \
useradd -r -g appuser -u 1001 -m -d /home/appuser appuser

WORKDIR /appuser

Expand All @@ -27,11 +37,18 @@ COPY --from=builder --chown=appuser:appuser /app /appuser
# Set the PATH to use the virtual environment
ENV PATH="/appuser/.venv/bin:$PATH"

ENV MCP_TRANSPORT="stdio"
ENV MCP_HOST="0.0.0.0"
ENV MCP_PORT="8000"
ENV MCP_PATH="/"
# Environment variables with defaults
ENV MCP_TRANSPORT="stdio" \
MCP_HOST="0.0.0.0" \
MCP_PORT="8000" \
MCP_PATH="/"

# Simple health check for HTTP transports (without external dependencies)
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
Copy link
Contributor

Choose a reason for hiding this comment

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

We can wait for this PR merge so that we have a dedicated health endpoint to check

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@arpit-at can we merge this since there are no dependencies yet and later I will replcae with ealth check endpoint?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Hk669 once the health check PR is merged, I will make this endpoint /health
please review

CMD if [ "$MCP_TRANSPORT" = "sse" ] || [ "$MCP_TRANSPORT" = "streamable-http" ]; then \
python -c "import urllib.request; urllib.request.urlopen('http://localhost:$MCP_PORT$MCP_PATH', timeout=5)" || exit 1; \
else exit 0; fi

USER appuser

ENTRYPOINT exec python server.py --transport "$MCP_TRANSPORT" --host "$MCP_HOST" --port "$MCP_PORT" --path "$MCP_PATH"
ENTRYPOINT ["sh", "-c", "exec python server.py --transport \"$MCP_TRANSPORT\" --host \"$MCP_HOST\" --port \"$MCP_PORT\" --path \"$MCP_PATH\""]
Copy link
Collaborator

Choose a reason for hiding this comment

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

why is this change even required? i think we have simpler version already!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

check docker docs: This is the preferred way.
https://docs.docker.com/reference/build-checks/json-args-recommended/
and
https://docs.docker.com/reference/dockerfile/#entrypoint

If we do not change this then

  1. Shell interprets the command and may not properly forward signals (SIGTERM, SIGINT)
  2. Can lead to forceful container kills instead of clean shutdowns
  3. Shell form is vulnerable to injection if environment variables contain special characters:

Advantages:
Proper Signal Handling: The exec ensures Python process becomes PID 1 and receives signals directly
Security: Variables are properly quoted and escaped
Predictable Behavior: No shell interpretation surprises
Docker Best Practice: Recommended by Docker documentation