Skip to content

Instantly share code, notes, and snippets.

@pamelafox
Last active December 2, 2025 13:38
Show Gist options
  • Select an option

  • Save pamelafox/b16f399f2dcab6f275eaa3df4a1215b1 to your computer and use it in GitHub Desktop.

Select an option

Save pamelafox/b16f399f2dcab6f275eaa3df4a1215b1 to your computer and use it in GitHub Desktop.
Dockerfile for FastMCP and uv
# ------------------- Stage 0: Base Stage ------------------------------
FROM python:3.13-alpine AS base
# Install tini, a tiny init for containers
RUN apk add --update --no-cache tini
# Install required packages for cryptography and ml-dtypes packages
# https://cryptography.io/en/latest/installation/#building-cryptography-on-linux
RUN apk add gcc g++ musl-dev python3-dev libffi-dev openssl-dev cargo pkgconfig
# ------------------- Stage 1: Build Stage ------------------------------
FROM base AS build
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /code
# Install dependencies first (for layer caching)
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --locked --no-install-project
# Copy the project and sync
COPY . .
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --locked
# ------------------- Stage 2: Final Stage ------------------------------
FROM base AS final
RUN addgroup -S app && adduser -S app -G app
COPY --from=build --chown=app:app /code /code
WORKDIR /code/servers
USER app
ENV PATH="/code/.venv/bin:$PATH"
EXPOSE 8000
ENTRYPOINT ["tini", "uvicorn", "deployed_mcp:app", "--host", "0.0.0.0", "--port", "8000"]
# ------------------- Stage 1: Build Stage ------------------------------
# We use Alpine for smaller image size (~329MB vs ~431MB for Debian slim).
# Trade-off: We must install build tools to compile native extensions (cryptography, etc.)
# since pre-built musl wheels aren't available. Debian -slim would skip compilation
# but produces a larger final image due to glibc wheel sizes.
FROM python:3.13-alpine AS build
# Install build dependencies for packages with native extensions (cryptography, etc.)
# https://cryptography.io/en/latest/installation/#building-cryptography-on-linux
RUN apk add --no-cache gcc g++ musl-dev python3-dev libffi-dev openssl-dev cargo pkgconfig
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /code
# Install dependencies first (for layer caching)
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --locked --no-install-project
# Copy the project and sync
COPY . .
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --locked
# ------------------- Stage 2: Final Stage ------------------------------
FROM python:3.13-alpine AS final
# Install tini, a tiny init for containers
RUN apk add --no-cache tini
RUN addgroup -S app && adduser -S app -G app
COPY --from=build --chown=app:app /code /code
WORKDIR /code/servers
USER app
ENV PATH="/code/.venv/bin:$PATH"
EXPOSE 8000
ENTRYPOINT ["tini", "uvicorn", "deployed_mcp:app", "--host", "0.0.0.0", "--port", "8000"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment