Skip to main content

Overview

Docker deployment provides a containerized, production-ready environment for the Secure MCP Gateway. The included Docker Compose stack bundles the gateway with a complete observability platform.

Prerequisites

  • Docker: 20.10 or higher
  • Docker Compose: v2.0 or higher
  • Git (for cloning the repository)

Verify Docker Installation

# Check Docker version
docker --version
# Expected: Docker version 20.10.0 or higher

# Check Docker Compose version
docker compose version
# Expected: Docker Compose version v2.0.0 or higher

# Verify Docker is running
docker ps

Quick Start

1

Build Docker Image

Build the gateway image from the repository:
# Clone repository (if not already done)
git clone https://github.com/enkryptai/secure-mcp-gateway
cd secure-mcp-gateway

# Build image
docker build -t secure-mcp-gateway .
Build time: ~2-5 minutes depending on your machine. The image includes Python 3.12, Node.js 22.x, and all gateway dependencies.
2

Generate Configuration

Generate the Docker-specific config file:
docker run --rm \
  -e HOST_OS=macos \
  -e HOST_ENKRYPT_HOME=$HOME/.enkrypt \
  -v ~/.enkrypt/docker:/app/.enkrypt/docker \
  --entrypoint python \
  secure-mcp-gateway \
  -m secure_mcp_gateway.cli generate-config
This creates:
  • macOS/Linux: ~/.enkrypt/docker/enkrypt_mcp_config.json
  • Windows: %USERPROFILE%\.enkrypt\docker\enkrypt_mcp_config.json
3

Install for Claude Desktop

Register the Docker gateway with Claude Desktop:
docker run --rm -i \
  -e HOST_OS=macos \
  -e HOST_ENKRYPT_HOME=$HOME/.enkrypt \
  -v ~/.enkrypt/docker:/app/.enkrypt/docker \
  -v ~/Library/Application\ Support/Claude:/app/.claude \
  --entrypoint python \
  secure-mcp-gateway \
  -m secure_mcp_gateway.cli install --client claude-desktop
Important: The generated config includes MCP_TRANSPORT=stdio for stdio mode communication. Restart Claude Desktop after installation.
4

Run Gateway Container

Start the gateway in detached mode:
docker run -d \
  --name secure-mcp-gateway \
  -p 8000:8000 \
  -v ~/.enkrypt/docker:/app/.enkrypt/docker \
  -e ENKRYPT_GATEWAY_KEY="<your_gateway_key>" \
  -e ENKRYPT_PROJECT_ID="<your_project_id>" \
  -e ENKRYPT_USER_ID="<your_user_id>" \
  secure-mcp-gateway
Replace <your_gateway_key>, <your_project_id>, and <your_user_id> with values from your generated config file.

Docker Compose Deployment

For production deployments, use Docker Compose to deploy the gateway with the complete observability stack.

Observability Stack Components

The infra/docker-compose.yml includes:

OpenTelemetry Collector

Receives OTLP traces, metrics, and logs from gateway

Jaeger

Distributed tracing visualization (port 16686)

Loki

Log aggregation and storage (port 3100)

Prometheus

Metrics storage and querying (port 9090)

Grafana

Unified dashboards for metrics, logs, traces (port 3000)

Docker Compose Configuration

infra/docker-compose.yml
name: secure-mcp-gateway-infra
services:
  # OpenTelemetry Collector - Central telemetry hub
  otel-collector:
    image: otel/opentelemetry-collector-contrib:0.134.1
    command: ["--config=/etc/otel-collector-config.yaml"]
    volumes:
      - ./otel_collector/otel-collector-config.yaml:/etc/otel-collector-config.yaml
    ports:
      - "4317:4317"   # OTLP gRPC receiver
      - "4318:4318"   # OTLP HTTP receiver
      - "8889:8889"   # Prometheus metrics exporter
    depends_on:
      - jaeger
      - loki

  # Jaeger - Distributed tracing
  jaeger:
    image: jaegertracing/all-in-one:1.73.0
    ports:
      - "16686:16686"  # Web UI
      - "14250:14250"  # gRPC collector endpoint
      - "16685:16685"  # Query port for Grafana
    environment:
      - LOG_LEVEL=debug
      - QUERY_BASE_PATH=/jaeger
      - COLLECTOR_OTLP_ENABLED=true

  # Loki - Log aggregation
  loki:
    image: grafana/loki:main-cadc824
    ports:
      - "3100:3100"
    volumes:
      - ./loki/loki-config.yaml:/etc/loki/local-config.yaml
    command: -config.file=/etc/loki/local-config.yaml

  # Prometheus - Metrics storage
  prometheus:
    image: prom/prometheus:v3.5.0
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
    depends_on:
      - otel-collector

  # Grafana - Visualization
  grafana:
    image: grafana/grafana:12.2.0-17535958692
    ports:
      - "3000:3000"
    environment:
      - GF_AUTH_ANONYMOUS_ENABLED=true
      - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
    volumes:
      - ./grafana/provisioning:/etc/grafana/provisioning
    depends_on:
      - loki
      - otel-collector
      - prometheus

Prometheus Configuration

infra/prometheus/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'otel-collector'
    static_configs:
      - targets: ['otel-collector:8889']

Launch Observability Stack

# Navigate to infrastructure directory
cd infra

# Start all services
docker compose up -d

# Check service status
docker compose ps

# View logs
docker compose logs -f

# Stop services
docker compose down

Access Dashboards

Once the stack is running:

Grafana

URL: http://localhost:3000Auth: Anonymous (Admin role)View unified dashboards with metrics, logs, and traces

Jaeger

URL: http://localhost:16686Search and analyze distributed traces

Prometheus

URL: http://localhost:9090Query metrics and view targets

Loki

URL: http://localhost:3100Query logs via API or Grafana

Dockerfile Breakdown

The gateway Dockerfile is a multi-runtime environment:
# Base: Ubuntu 24.04 LTS for stability
FROM ubuntu:24.04

WORKDIR /app

# Install system dependencies:
# - Python 3.12 (pip, uv, pipx)
# - Node.js 22.x LTS (npm, npx)
# - Build tools (gcc, g++, make)
# - Utilities (git, jq, yq, curl, ssh)
RUN apt-get update && apt-get install -y \
    python3.12 python3.12-dev python3-pip \
    build-essential gcc g++ make \
    nodejs npm curl wget git jq yq \
    openssh-client unzip zip tar \
    && rm -rf /var/lib/apt/lists/*

# Set Python 3.12 as default
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 1

# Install uv (fast Python package installer)
RUN pip3 install --break-system-packages uv

# Install Node.js LTS (22.x)
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
    && apt-get install -y nodejs \
    && npm install -g npm@latest

# Copy and install Python dependencies
COPY requirements.txt requirements-dev.txt ./
RUN pip3 install --break-system-packages --upgrade pip setuptools wheel \
    && pip3 install --break-system-packages -r requirements.txt \
    && pip3 install --break-system-packages -r requirements-dev.txt

# Copy source code and metadata
COPY src src
COPY setup.py MANIFEST.in pyproject.toml ./
COPY CHANGELOG.md LICENSE.txt README.md README_PYPI.md ./

# Configure for ingress
ENV HOST=0.0.0.0
ENV FASTAPI_HOST=0.0.0.0

# Build and install package
RUN python3 -m build && pip3 install --break-system-packages .

EXPOSE 8000

# Entrypoint: Run gateway server
ENTRYPOST ["python3", "src/secure_mcp_gateway/gateway.py"]

Image Features

  • pip: Standard package installer
  • uv: Fast Rust-based package installer (10-100x faster)
  • pipx: Isolated Python app installations
  • Supports Python-based MCP servers
  • npm: Package manager
  • npx: Package executor
  • Supports JavaScript/TypeScript MCP servers (e.g., GitHub MCP)
  • gcc, g++, make for compiling native dependencies
  • Python development headers
  • SSL, SQLite, readline libraries
  • Git: Repository operations
  • jq/yq: JSON/YAML processing
  • curl/wget: HTTP downloads
  • ssh: Secure remote access
  • zip/tar: Archive handling

Claude Desktop Configuration

After Docker installation, your Claude config will look like:
claude_desktop_config.json
{
  "mcpServers": {
    "Enkrypt Secure MCP Gateway": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "-e",
        "MCP_TRANSPORT=stdio",
        "-v",
        "/Users/user/.enkrypt/docker:/app/.enkrypt/docker",
        "secure-mcp-gateway"
      ],
      "env": {
        "ENKRYPT_GATEWAY_KEY": "2W8UupCkazk4SsOcSu_...",
        "ENKRYPT_PROJECT_ID": "3c09f06c-...",
        "ENKRYPT_USER_ID": "6469a670-..."
      }
    }
  }
}
The MCP_TRANSPORT=stdio environment variable enables stdio communication mode for Claude Desktop integration.

Environment Variables

Key environment variables for Docker deployment:
VariableDescriptionDefault
HOSTGateway bind address0.0.0.0
FASTAPI_HOSTFastAPI server bind address0.0.0.0
ENKRYPT_GATEWAY_KEYAPI key for authentication(from config)
ENKRYPT_PROJECT_IDProject identifier(from config)
ENKRYPT_USER_IDUser identifier(from config)
MCP_TRANSPORTMCP communication modestdio
DEBIAN_FRONTENDPrevent interactive promptsnoninteractive

Volumes

Mount these volumes for persistence:
# Configuration directory
-v ~/.enkrypt/docker:/app/.enkrypt/docker

# Logs directory (optional)
-v ~/.enkrypt/logs:/app/.enkrypt/logs

# Custom MCP servers (optional)
-v ~/mcp-servers:/app/mcp-servers

Networking

Exposed Ports

  • 8000: Gateway MCP server (streamable HTTP)
  • 8001: FastAPI REST API (if enabled)

Docker Network

The Compose stack creates a bridge network for inter-service communication:
# View network
docker network inspect secure-mcp-gateway-infra_default

# Services can reference each other by name:
# - otel-collector:4317
# - prometheus:9090
# - jaeger:16686

Health Checks

# Check gateway health
curl http://localhost:8000/health

# Check OpenTelemetry Collector
curl http://localhost:8889/metrics

# Check Prometheus targets
curl http://localhost:9090/api/v1/targets

# Check Loki ready
curl http://localhost:3100/ready

Monitoring Gateway Logs

# Follow gateway logs
docker logs -f secure-mcp-gateway

# View last 100 lines
docker logs --tail 100 secure-mcp-gateway

# View logs with timestamps
docker logs -t secure-mcp-gateway

# View all services (Compose)
docker compose logs -f

Troubleshooting

Container Won’t Start

# Check container logs
docker logs secure-mcp-gateway

# Inspect container
docker inspect secure-mcp-gateway

# Verify image built correctly
docker images | grep secure-mcp-gateway

Port Conflicts

# Check if ports are in use
lsof -i :8000
lsof -i :3000

# Change port mapping
docker run -p 8080:8000 ...

Volume Permissions

# macOS/Linux - Fix permissions
chmod -R 755 ~/.enkrypt/docker

# Check volume mounts
docker inspect secure-mcp-gateway | grep Mounts -A 10

Observability Stack Issues

# Restart services
docker compose restart

# Rebuild services
docker compose up -d --build

# Check service health
docker compose ps

# View specific service logs
docker compose logs grafana
docker compose logs otel-collector

Updating

# Pull latest code
git pull origin main

# Rebuild image
docker build -t secure-mcp-gateway .

# Stop old container
docker stop secure-mcp-gateway
docker rm secure-mcp-gateway

# Start new container
docker run -d ...

# Or with Compose
docker compose down
docker compose up -d --build

Production Considerations

Security Notes:
  • Docker-in-Docker (DinD) is commented out in the Dockerfile for security reasons
  • Only enable DinD if you understand the security implications
  • Use secrets management for API keys in production
  • Enable TLS for OTLP endpoints

Use External Cache

Deploy Redis/KeyDB for distributed caching across multiple gateway instances

Enable TLS

Configure TLS certificates for secure communication with OTLP collector

Resource Limits

Set memory and CPU limits:
docker run --memory="2g" --cpus="1.5" ...

Persistent Storage

Use named volumes for Prometheus, Loki, and Grafana data persistence

Next Steps

Deployment Patterns

Learn about production deployment architectures

External Cache Setup

Configure Redis/KeyDB for distributed caching

Monitoring Guide

Deep dive into metrics, traces, and logs

CLI Commands

Manage Docker deployment with CLI

Build docs developers (and LLMs) love