-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathDockerfile
More file actions
70 lines (54 loc) · 2.79 KB
/
Dockerfile
File metadata and controls
70 lines (54 loc) · 2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# Multi-stage build for Python MCP server with uv package manager
# Base: python:3.13-slim-trixie (Debian 13, 2026 standard)
# Stage 1: Builder - compile dependencies with uv
# python:3.13-slim-trixie
FROM python:3.13-slim-trixie@sha256:d168b8d9eb761f4d3fe305ebd04aeb7e7f2de0297cec5fb2f8f6403244621664 AS builder
# Copy uv from official distribution image (not using as base to keep image small)
# ghcr.io/astral-sh/uv:0.11.3
COPY --from=ghcr.io/astral-sh/uv:0.11.3@sha256:90bbb3c16635e9627f49eec6539f956d70746c409209041800a0280b93152823 /uv /usr/local/bin/uv
# Compile bytecode and optimize cache locality for production
ENV UV_COMPILE_BYTECODE=1 \
UV_LINK_MODE=copy \
UV_PYTHON_DOWNLOADS=0
WORKDIR /app
# Install runtime dependencies only (no dev deps, no editable install)
# --no-editable ensures the package is copied into site-packages, not linked via .pth
# Use cache mounts for uv's package cache to speed up builds
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
--mount=type=bind,source=uv.lock,target=uv.lock \
uv sync --no-install-project --no-dev --no-editable --locked
# Copy source code and install the project into the venv (non-editable)
# Non-editable install is required because only .venv is copied to runtime stage
COPY . .
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --no-dev --no-editable --locked
# Stage 2: Runtime - minimal production image
# python:3.13-slim-trixie
FROM python:3.13-slim-trixie@sha256:d168b8d9eb761f4d3fe305ebd04aeb7e7f2de0297cec5fb2f8f6403244621664
# Create non-root user for security (uid 1000 standard)
RUN useradd --uid 1000 --create-home --shell /sbin/nologin sshmcp
WORKDIR /app
# Copy virtual environment from builder with proper ownership
COPY --from=builder --chown=sshmcp:sshmcp /app/.venv /app/.venv
# Add venv to PATH
ENV PATH=/app/.venv/bin:$PATH \
PYTHONUNBUFFERED=1
# Switch to non-root user
USER sshmcp
# Port 8000 is the default for SSH_MCP_TRANSPORT=http. Only relevant when
# running the streamable-HTTP transport; stdio deployments ignore this.
# Override via SSH_MCP_HTTP_PORT env var and republish with -p.
EXPOSE 8000
# HEALTHCHECK: use the built-in ``ssh-mcp healthcheck`` subcommand which
# auto-detects transport (stdio vs streamable-http) and performs a real
# MCP initialize handshake in HTTP mode. Reads the same env vars as the
# server itself (SSH_MCP_TRANSPORT, SSH_MCP_HTTP_PORT, SSH_MCP_HTTP_TOKEN,
# SSH_MCP_HTTP_TOKEN_FILE, SSH_MCP_HTTP_AUTH).
#
# start_period=10s covers startup for HTTP transport (FastMCP session
# manager init + uvicorn bind). interval=30s is standard.
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD ssh-mcp healthcheck
# Entry point: invoke the console script installed by uv
ENTRYPOINT ["ssh-mcp"]