# Building Docker Images for Python MCP Servers: A Production Guide with the Wordle Example

> Learn to build minimal ~30MB Docker images for Python MCP servers using multistage Dockerfiles and Astral's uv package manager. Optimize your production deployments today.

- Repository: [CSK/mcp-wordle-python](https://github.com/cr2007/mcp-wordle-python)
- Tags: tutorial
- Published: 2026-02-28

---

**Use a multistage Dockerfile with Astral's uv package manager to build deterministic, minimal images (~30MB) for Python MCP servers, separating the build environment from the final production stage.**

The Model Context Protocol (MCP) enables AI assistants to interact with external data sources through standardized server implementations. When deploying Python-based MCP servers in production, containerization ensures consistent environments and easy distribution. This guide examines the `cr2007/mcp-wordle-python` repository to demonstrate building Docker images for Python MCP servers using modern best practices.

## Architecture of the Wordle MCP Server

The repository implements a minimal MCP server with three core components that influence the containerization strategy.

### FastMCP Integration

The entry point at [`src/mcp_wordle/main.py`](https://github.com/cr2007/mcp-wordle-python/blob/main/src/mcp_wordle/main.py) instantiates a `FastMCP` object named **WordleMCP** and registers the asynchronous tool `get_wordle_data`. This tool fetches the official Wordle JSON from the New York Times API and returns the parsed solution.

### Project Configuration

The [`pyproject.toml`](https://github.com/cr2007/mcp-wordle-python/blob/main/pyproject.toml) defines runtime dependencies (`fastmcp` and `requests`) and declares the `mcp-wordle` console script as the server entry point. This metadata drives the installation process inside the container.

### Container Build Pipeline

A multistage Dockerfile leverages **uv** (Astral's high-performance Python package manager) to create reproducible builds with minimal layer caching invalidation.

## Building Docker Images for Python MCP Servers

The Dockerfile implements a two-stage build strategy that separates dependency resolution from the final runtime environment.

### The Builder Stage

The first stage uses `ghcr.io/astral-sh/uv:0.7-python3.10-bookworm-slim` as the base image. This stage installs the project into an isolated virtual environment:

```dockerfile
FROM ghcr.io/astral-sh/uv:0.7-python3.10-bookworm-slim AS builder
WORKDIR /app
COPY pyproject.toml .
COPY src ./src
RUN uv sync --locked --no-dev

```

The `uv sync --locked --no-dev` command ensures deterministic builds using the locked dependency tree while excluding development dependencies.

### The Production Stage

The final stage uses the official `python:3.10-slim-bookworm` image and copies only the prepared application directory from the builder:

```dockerfile
FROM python:3.10-slim-bookworm
COPY --from=builder /app /app
ENV PATH="/app/.venv/bin:$PATH"
ENV PYTHONPATH="/app/src"
ENTRYPOINT ["mcp-wordle"]

```

This approach yields an image size of approximately **30MB**, containing only the Python runtime, virtual environment, and application code.

## Running the MCP Server Container

Configure your MCP client to launch the container using the Docker runtime:

```json
{
  "mcpServers": {
    "Wordle MCP (Python)": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "--init",
        "-e",
        "DOCKER_CONTAINER=true",
        "ghcr.io/cr2007/mcp-wordle-python:latest"
      ]
    }
  }
}

```

Pre-pull the image to avoid initialization delays:

```bash
docker pull ghcr.io/cr2007/mcp-wordle-python:latest

```

For local development without Docker, use `uvx` to run directly from the repository:

```json
{
  "mcpServers": {
    "Wordle MCP (Python)": {
      "command": "uvx",
      "args": [
        "--from",
        "git+https://github.com/cr2007/mcp-wordle-python",
        "mcp-wordle"
      ]
    }
  }
}

```

## Summary

- **Multistage builds** separate dependency resolution from runtime, minimizing image size and attack surface when building Docker images for Python MCP servers.
- **Astral's uv** provides deterministic, locked dependency installation via `uv sync --locked --no-dev`, significantly faster than traditional pip workflows.
- The **Wordle MCP server** demonstrates production-ready containerization at approximately 30MB using `python:3.10-slim-bookworm` and the uv builder pattern.
- Configure MCP clients to invoke containers via `docker run` with interactive flags (`-i`, `--init`) for proper signal handling and stdio communication.

## Frequently Asked Questions

### What is the recommended base image for Python MCP servers?

The `python:3.10-slim-bookworm` image (or similar slim variants) provides a minimal Debian-based runtime without unnecessary development tools. For the build stage, use `ghcr.io/astral-sh/uv:0.7-python3.10-bookworm-slim` to leverage the uv package manager's performance advantages and dependency locking capabilities.

### How does uv improve Docker builds for Python MCP servers?

Uv implements a universal lockfile (`uv.lock`) that guarantees reproducible installations across environments. The `uv sync --locked --no-dev` command installs only production dependencies in a single layer, reducing build time and image size compared to traditional pip workflows that often require separate dependency resolution steps and larger base images.

### Can I run the Wordle MCP server without Docker?

Yes. The repository supports running directly via `uvx`, which downloads and executes the package from GitHub without local cloning. Alternatively, install the package locally with `pip install git+https://github.com/cr2007/mcp-wordle-python` and invoke the `mcp-wordle` console script directly from your shell.

### Why is the Docker image only 30MB when Python images are usually larger?

The minimal size results from three optimizations: using the slim Python base image (removing compilers and dev tools), excluding development dependencies via `--no-dev`, and copying only the compiled virtual environment from the builder stage. The final image contains only the Python runtime, the application code in `/app/src`, and the installed packages in `/app/.venv`.