MCP Hub
Back to servers

MCP-server-docker-guide

Complete guide to setting up Model Context Protocol (MCP) servers with Docker on Linux. Step-by-step tutorial for Claude Desktop, Cursor, and Windsurf integration.

Stars
2
Updated
Nov 20, 2025
Validated
Jan 9, 2026

Setting Up MCP Servers with Docker

A practical guide to running Model Context Protocol (MCP) servers using Docker, enabling AI assistants to interact with your local tools, files, and APIs in a safe, containerized environment.


What is MCP?

Model Context Protocol (MCP) is an open standard that allows AI models to connect with external tools, APIs, and databases through a standardized interface. Instead of building custom integrations for every tool, MCP provides a universal plug-and-play system for AI applications.

Key Benefits

  • Reduces hallucinations by providing LLMs with access to real-time, reliable data sources.
  • Enables AI agents to perform complex tasks like file operations, web searches, and database queries.
  • Modular architecture allows switching models or tools without changing integration code.
  • Standardized protocol using JSON-RPC 2.0 for communication.

Architecture Overview

MCP follows a client-host-server architecture with three main components:

  • Host: Applications like Claude Desktop, Cursor, or Windsurf that contain the LLM
  • Client: Lightweight protocol client embedded within the host, maintaining 1:1 connections with servers
  • Server: Independent processes that expose capabilities (data access, tools, prompts) through the MCP standard

Transport Methods

  • STDIO: For local integrations where the server runs in the same environment (most common)
  • HTTP+SSE: For remote connections using Server-Sent Events

Why Use Docker for MCP?

  • Isolation: Each MCP server runs in its own container, preventing conflicts
  • No dependency hell: Skip installing Node.js, Python, or other runtimes on your system
  • Easy cleanup: Remove containers without affecting your base system
  • Portability: Same setup works across different Linux distributions
  • Security: Containers limit filesystem and network access to only what you specify

⚠️ Security Notice

IMPORTANT: MCP servers have access to your system resources. Always:

  • ✅ Review server source code before building
  • ✅ Use Docker containers for isolation (recommended)
  • ✅ Use read-only mounts (:ro) when possible
  • ✅ Store API keys in environment variables, not config files
  • ✅ Limit filesystem access to specific directories only
  • ✅ Never expose MCP servers directly to the internet
  • ✅ Keep Docker images updated regularly

For detailed security guidelines, see MCP Security Best Practices.

Prerequisites

Before starting, ensure you have:

Quick Docker Setup (Linux)

Debian/Ubuntu

sudo apt update
sudo apt install docker.io docker-compose
sudo systemctl start docker
sudo systemctl enable docker

Arch Linux

sudo pacman -S docker docker-compose
sudo systemctl start docker.service
sudo systemctl enable docker.service

Fedora

sudo dnf install docker docker-compose
sudo systemctl start docker
sudo systemctl enable docker

Add your user to docker group (all distributions)

sudo usermod -aG docker $USER

Important: Log out and log back in for group changes to take effect.

Verify Docker Installation

docker --version
docker run hello-world

Step 1: Clone the Official MCP Servers Repository

git clone https://github.com/modelcontextprotocol/servers.git
cd servers

Step 2: Build MCP Server Images

Create a build script to compile all available MCP servers:

nano build_servers.sh

Paste the following content:

#!/bin/bash
set -euo pipefail


# Security: Verify we're in the official MCP repository
if [ ! -f "CONTRIBUTING.md" ] || ! grep -q "modelcontextprotocol" "CONTRIBUTING.md" 2>/dev/null; then
    echo "⚠️  Warning: Not in official MCP servers repository"
    echo "For security, only build from trusted sources"
    read -p "Continue anyway? (yes/no): " confirm
    if [ "$confirm" != "yes" ]; then
        exit 1
    fi
fi

SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE}")" && pwd)
DOCKER_SRC_DIR="$SCRIPT_DIR/src"

for folder in "$DOCKER_SRC_DIR"/*; do
if [ -d "$folder" ]; then
folder_name=$(basename "$folder")
# Skip folders that don't need building
  if [ "$folder_name" == "redis" ]; then
        echo "⏭️  Skipping '$folder_name': Redis does not require build"
        continue
    fi
    
    dockerfile="$folder/Dockerfile"
    
    if [ -f "$dockerfile" ]; then
        # Check if Dockerfile references uv.lock
        if grep -q "uv\.lock" "$dockerfile"; then
            if [ ! -f "$folder/uv.lock" ]; then
                echo "⏭️  Skipping '$folder_name': uv.lock not found"
                continue
            fi
        fi
        
        # Determine build context
        if grep -E -q "COPY[[:space:]]+src/${folder_name}\b" "$dockerfile"; then
            context="$SCRIPT_DIR"
            echo "🔨 Building '$folder_name' with repository root as context"
        else
            context="$folder"
            echo "🔨 Building '$folder_name' with project folder as context"
        fi
        
        docker build -t "$folder_name" -f "$dockerfile" "$context"
        echo "✅ Successfully built '$folder_name'"
    else
        echo "⏭️  Skipping '$folder_name': Dockerfile not found"
    fi
fi
done

echo ""
echo "🎉 Build complete! Run 'docker images' to see all built MCP servers."

Make the script executable and run it:

chmod +x build_servers.sh
./build_servers.sh

Note: Building may take 10-20 minutes depending on your internet speed and system performance.

Verify Built Images

docker images

You should see images like: filesystem, brave-search, git, sqlite, fetch, puppeteer, memory, google-maps, and more


Step 3: Configure Your MCP Client

MCP servers communicate via STDIO (standard input/output), not HTTP. Configuration differs by client.

For Claude Desktop (Linux)

Create or edit the configuration file:

mkdir -p ~/.config/Claude
nano ~/.config/Claude/claude_desktop_config.json

Add the following configuration:

{
  "mcpServers": {
    "filesystem": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "--mount", "type=bind,src=/home/YOUR_USERNAME/mcp-workspace,dst=/workspace,readonly",
        "--memory", "512m",
        "--cpus", "0.5",
        "filesystem",
        "/workspace"
      ]
    },
    "git": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "--mount", "type=bind,src=/path/to/your/repo,dst=/repo",
        "git",
        "--repository", "/repo"
      ]
    },
    "brave-search": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "BRAVE_API_KEY",
        "brave-search"
      ],
      "env": {
        "BRAVE_API_KEY": "${BRAVE_API_KEY}"
      }
    },
    "sqlite": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "--mount", "type=bind,src=/home/YOUR_USERNAME/databases,dst=/data",
        "sqlite"
      ]
    },
    "fetch": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "fetch"]
    },
    "memory": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "memory"]
    },
    "puppeteer": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "--init",
        "--cap-drop=ALL",
        "--security-opt=no-new-privileges",
        "-e", "DOCKER_CONTAINER=true",
        "puppeteer"
      ]
    },
    "google-maps": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "GOOGLE_MAPS_API_KEY",
        "google-maps"
      ],
      "env": {
        "GOOGLE_MAPS_API_KEY": "${GOOGLE_MAPS_API_KEY}"
      }
    }
  }
}

Configuration Notes

IMPORTANT: Update these values:

  1. Filesystem path: Replace /home/YOUR_USERNAME/mcp-workspace with your actual workspace directory mkdir -p ~/mcp-workspace
  2. API keys: Replace YOUR_BRAVE_API_KEY_HERE and YOUR_GOOGLE_MAPS_API_KEY_HERE with your actual keys
  3. For other MCP clients: Check their documentation for configuration file locations

CRITICAL UPDATES REQUIRED:

  1. Filesystem path:

    • Create workspace directory:
      mkdir -p ~/mcp-workspace
      
    • Replace /home/YOUR_USERNAME/ with your actual username
    • Use absolute paths only (no ~ or relative paths)
  2. API Keys:

    • Set as environment variables (see Environment Variables section)
    • Never commit config files with real API keys to Git
    • Use .gitignore to exclude your config:
      echo "claude_desktop_config.json" >> .gitignore
      
  3. Git Repository Path:

    • Must point to an existing Git repository
    • Use absolute path: /home/username/my-repo

Step 4: Setting Up Environment Variables Securely

Instead of hardcoding API keys in the config file, store them as environment variables:

Linux (Bash/Zsh)

Add to ~/.bashrc or ~/.zshrc:

export BRAVE_API_KEY="your-brave-api-key-here"
export GOOGLE_MAPS_API_KEY="your-google-maps-api-key-here"

Then reload:

source ~/.bashrc # or ~/.zshrc

Verify Variables Are Set

echo $BRAVE_API_KEY

Note: Environment variables must be set before starting Claude Desktop.


Step 5: Test Your Setup

> Restart Your MCP Client

Completely quit and restart your MCP client (don't just reload) to load the new configuration.

> Verify Server Connection

  1. Completely quit your MCP client (Claude Desktop/Cursor/Windsurf)
  2. Restart the application
  3. Check server status:
    • Claude Desktop: Settings → Developer → MCP
    • Look for your servers listed as "Connected" or "Running"

Check Logs If Servers Don't Connect

Claude Desktop Logs (Linux):

~/.config/Claude/logs/mcp*.log

Common log issues:

  • "command not found" → Docker not in PATH
  • "permission denied" → Not in docker group
  • "no such file" → Check mount paths are absolute and exist

Test Each Server

Try these commands in your AI assistant: Filesystem:

"Create a new file called test.txt in my workspace"

Brave Search:

"Search the web for latest Docker updates using brave-search"

Git: "Show me the git status of the current repository"

SQLite:

"Create a new SQLite database for tracking my projects"

Memory:

"Remember that my favorite programming language is Python"

The AI assistant should request permission before executing operations and show results.


Available MCP Servers

ServerDescriptionRequires API Key
filesystemSecure file operations (read, write, delete)No
brave-searchWeb search via Brave Search APIYes
gitGit repository operations and version controlNo
sqliteSQLite database creation and queriesNo
fetchFetch and parse web contentNo
puppeteerBrowser automation and web scrapingNo
memoryPersistent knowledge graph storageNo
google-mapsLocation services and directionsYes
postgresPostgreSQL database accessConnection string
sequentialthinkingProblem-solving workflowsNo

Monitoring Resource Usage

Keep an eye on your MCP servers:

Real-time container stats

docker stats

Check disk usage

docker system df

View container logs

docker logs <container-name>

Set appropriate resource limits based on your system:

System RAMRecommended Memory LimitRecommended CPU Limit
4GB256MB per server0.25 CPU
8GB512MB per server0.5 CPU
16GB+1GB per server1.0 CPU

Handy Docker Commands

List all built images:

docker images

List running containers:

docker ps

List all containers (including stopped):

docker ps -a

Remove unused containers:

docker container prune

Remove unused images:

docker image prune

View logs for a specific run (if it fails):

docker logs <container_id>

Test a server manually:

docker run -i --rm filesystem

Remove a specific image:

docker rmi <image_name>

Troubleshooting

Servers Not Appearing in Client

  1. Completely restart your MCP client (quit and reopen, don't just reload)
  2. Verify Docker is running: systemctl status docker or docker ps
  3. Check configuration file for JSON syntax errors
  4. Ensure all file paths are absolute, not relative

Permission Errors

Verify you're in the docker group

groups $USER

If not, add yourself and log out/in

sudo usermod -aG docker $USER

Filesystem Mount Errors

  • Ensure the directory exists:
    mkdir -p ~/mcp-workspace
    
  • Use absolute paths only (no ~ or relative paths)
  • Check read/write permissions:
    ls -la ~/mcp-workspace
    

API Key Failures

  • Verify no extra spaces or quotes in API keys
  • Test API keys directly with curl if possible
  • Check environment variables are properly set in config

Build Failures

Clean Docker cache and rebuild
docker system prune -a
./build_servers.sh

Docker Security Errors

"Operation not permitted" errors:

Add security context

--security-opt label=disable

"Cannot connect to Docker daemon:"

Check Docker is running

sudo systemctl status docker

Start if needed

sudo systemctl start docker

Resource limit errors:

Check Docker resources

docker system df

Clean up if needed

docker system prune -a

Security Best Practices

🔒 Essential Security Measures

  1. Use Read-Only Mounts by Default
--mount type=bind,src=/path,dst=/workspace,readonly

Only use read-write when necessary for the server's function.

  1. Set Resource Limits
--memory 512m --cpus 0.5

Prevents runaway containers from consuming all system resources.

  1. Never Hardcode Secrets
  • Bad: "BRAVE_API_KEY": "BSA123456789"
  • Good: "BRAVE_API_KEY": "${BRAVE_API_KEY}"

Store secrets in environment variables or Docker secrets.

  1. Limit Filesystem Access Only mount specific directories the AI needs:
  • Good: Limited access --mount type=bind,src=/home/user/documents,dst=/workspace

  • Bad: Too broad --mount type=bind,src=/home/user,dst=/workspace

  1. Drop Unnecessary Capabilities For security-sensitive servers like Puppeteer:
--cap-drop=ALL --security-opt=no-new-privileges
  1. Disable Network When Not Needed
--network none

Use for local-only servers like filesystem or SQLite.

  1. Regular Updates

Pull latest official servers

cd servers && git pull

Rebuild images

./build_servers.sh

Remove old images

docker image prune
  1. Audit Logging Monitor MCP activity by checking Claude Desktop logs regularly:
tail -f ~/.config/Claude/logs/mcp*.log

🚨 Security Red Flags

DO NOT use servers that:

  • Request root/admin privileges
  • Want access to your entire home directory
  • Lack proper documentation or source code
  • Come from untrusted sources
  • Have no version control history

🛡️ Zero-Trust Principles

  • Assume all MCP servers could be compromised
  • Grant minimum necessary permissions
  • Regularly review what servers can access
  • Remove unused servers from configuration

Advanced: Custom MCP Servers

Want to build your own MCP server? Check these resources:


Resources


💡 Tip: Docker makes experimenting with MCP servers safe and simple — if something breaks, just remove the container and start fresh. No system-wide installations to worry about.


Contributing

Contributions are welcome! Feel free to:

  • Open issues for bugs or suggestions
  • Submit pull requests with improvements
  • Fork and create your own version

This project is meant to be community-maintained and updated over time.

License

This guide is released under the CC0 v1.0 License. Use it freely, modify it, share it - no restrictions!

Reviews

No reviews yet

Sign in to write a review