# ESXi MCP Server - Modern Python with uv # Multi-stage build for optimal image size # Build stage FROM ghcr.io/astral-sh/uv:python3.11-bookworm-slim AS builder WORKDIR /app # Enable bytecode compilation for production ENV UV_COMPILE_BYTECODE=1 ENV UV_LINK_MODE=copy # Install dependencies first (cached layer) 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 --frozen --no-install-project --no-dev # Install project COPY pyproject.toml uv.lock ./ COPY src ./src RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --frozen --no-dev --no-editable # Production stage FROM python:3.11-slim-bookworm AS production # Create non-root user RUN groupadd -r mcpuser && useradd -r -g mcpuser mcpuser WORKDIR /app # Install runtime dependencies only RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ && rm -rf /var/lib/apt/lists/* \ && apt-get clean # Copy virtual environment from builder COPY --from=builder /app/.venv /app/.venv # Create directories RUN mkdir -p /app/logs /app/config \ && chown -R mcpuser:mcpuser /app # Environment configuration ENV PATH="/app/.venv/bin:$PATH" ENV PYTHONUNBUFFERED=1 ENV PYTHONDONTWRITEBYTECODE=1 # Default to SSE transport for Docker ENV MCP_TRANSPORT=sse ENV MCP_HOST=0.0.0.0 ENV MCP_PORT=8080 # Switch to non-root user USER mcpuser EXPOSE 8080 # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \ CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8080')" || exit 1 # Run the MCP server ENTRYPOINT ["esxi-mcp-server"] CMD ["--transport", "sse"]