csharp-sdk/docs/concepts/deployment/docker.md
John McKillip 71d7eead40
Augment conceptual docs with Docker-based MCP server deployment guidance (#1423)
Add a Docker deployment guide for ASP.NET Core MCP servers using Streamable HTTP (docs/concepts/deployment/docker.md), a Deployment/Docker entry in the conceptual nav (toc.yml, index.md), and cross-links from the transports and getting-started guides.
2026-07-20 04:50:08 -07:00

112 lines
3.4 KiB
Markdown

---
title: Docker Deployment
author: john-mckillip
description: How to run ASP.NET Core MCP servers in Docker containers using Streamable HTTP transport.
uid: docker-deployment
---
## Docker deployment for MCP servers
Docker is a practical way to package and run MCP servers consistently across development, CI, and production environments. For HTTP-based MCP servers, use ASP.NET Core hosting with Streamable HTTP.
This guide assumes you already have an ASP.NET Core MCP server configured with `ModelContextProtocol.AspNetCore`, `WithHttpTransport()`, and `MapMcp()`.
<!-- mlc-disable-next-line -->
> [!TIP]
> For local, process-based integrations where the client launches the server directly, stdio is often simpler. For remote and containerized deployments, Streamable HTTP is the recommended transport.
### Baseline server
A minimal HTTP-based MCP server looks like this:
```csharp
using ModelContextProtocol.Server;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMcpServer()
.WithHttpTransport()
.WithToolsFromAssembly();
var app = builder.Build();
app.MapMcp("/mcp");
app.Run();
```
### Dockerfile
Use a multi-stage Docker build so SDK tooling stays in the build stage and only runtime dependencies are shipped in the final image.
```dockerfile
# Build stage
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY . .
RUN dotnet restore
RUN dotnet publish -c Release -o /app/publish
# Runtime stage
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
WORKDIR /app
COPY --from=build /app/publish .
# MCP HTTP endpoint listens on 8080 inside container
ENV ASPNETCORE_URLS=http://+:8080
EXPOSE 8080
ENTRYPOINT ["dotnet", "MyMcpServer.dll"]
```
Replace `MyMcpServer.dll` with your server assembly output name.
### Build and run
Build the image:
```bash
docker build -t my-mcp-server:latest .
```
Run the container and map host port `3001` to container port `8080`:
```bash
docker run --rm -p 3001:8080 my-mcp-server:latest
```
With the baseline route above (`app.MapMcp("/mcp")`), clients connect to the Streamable HTTP endpoint at `http://localhost:3001/mcp`.
Streamable HTTP is the recommended transport for containerized MCP servers. The legacy SSE endpoints (`/mcp/sse` and `/mcp/message`) are not mapped by default, and the option to enable them is obsolete. See [Transports](../transports/transports.md) for details.
### Configuration and secrets
Pass configuration through environment variables rather than baking secrets into the image:
```bash
docker run --rm -p 3001:8080 \
-e ASPNETCORE_ENVIRONMENT=Production \
-e MYAPP__APIKEY=example \
my-mcp-server:latest
```
ASP.NET Core binds `MYAPP__APIKEY` to `MYAPP:APIKEY` in configuration.
<!-- mlc-disable-next-line -->
> [!IMPORTANT]
> Do not commit real tokens or credentials into Dockerfiles, compose files, or source code. Use runtime environment variables or an external secret store.
### Health and readiness
For container orchestrators, add an HTTP health endpoint and use it for readiness/liveness checks. Keep MCP traffic on your mapped MCP route and health probes on a separate route.
### Reverse proxies and forwarded headers
If your container is behind a reverse proxy (for example, ingress or load balancers), ensure forwarded headers are handled correctly so auth and origin metadata flow to the MCP server as expected.
See also:
- [Transports](../transports/transports.md)
- [Getting Started](../getting-started.md)
- [HTTP Context](../httpcontext/httpcontext.md)