How Your MCP Config Is Leaking Docker Containers (And How To Fix It)

Claude Code sessions can silently orphan Docker containers from MCP servers. Check your system and switch to `uvx` to fix it.

4h ago·3 min read·4 views·via reddit_claude, hn_claude_code
Share:

The Silent Resource Leak

If you use Docker-based Model Context Protocol (MCP) servers with Claude Code, you might be accumulating dozens of "zombie" containers that never get cleaned up. This happens because of how Claude Code's process lifecycle interacts with Docker's design.

When you start a Claude Code session, it spins up fresh Docker containers for each configured MCP tool (like a database browser or filesystem tool). The problem occurs when the session ends. If you close the IDE or terminal, Claude Code exits by closing the standard input (stdin) pipe to the docker run process. A broken pipe kills the process, but that process never gets a chance to signal the Docker daemon to stop the container. The container is orphaned and keeps running indefinitely.

The common fix of adding the --rm flag to docker run doesn't solve this. That flag only removes a container after it stops. Since these containers never receive a stop command, they never get removed.

How To Check For Leaks

Run this command in your terminal to see if you have any leaked containers:

docker ps | grep mcp

The original poster found 66 containers running from old Claude Code sessions. Each container consumes memory and CPU resources.

The Recommended Fix: Use uvx

The solution is to avoid Docker for MCP servers when possible. Instead, use tools that run as normal child processes, which get properly cleaned up when the parent process (Claude Code) exits.

For Python-based MCP servers, use uvx from the uv project. uvx runs tools directly in isolated environments without container overhead, and more importantly, it allows for proper process lifecycle management.

Example claude_desktop_config.json change:

Instead of:

"mcpServers": {
  "my-tool": {
    "command": "docker",
    "args": ["run", "--rm", "-i", "my-mcp-image"]
  }
}

Use:

"mcpServers": {
  "my-tool": {
    "command": "uvx",
    "args": ["mcp-my-tool"]
  }
}

Cleaning Up Existing Leaks

First, stop all the orphaned containers:

docker stop $(docker ps -q --filter "name=mcp")

Then remove them:

docker rm $(docker ps -a -q --filter "name=mcp")

Be careful if you have other containers with "mcp" in their names that you want to keep. You can manually review the list from docker ps | grep mcp first.

When Docker Is Still Necessary

Some MCP servers might require Docker due to complex dependencies or system isolation needs. For these cases, consider:

  1. Using Docker Compose with explicit cleanup: Create a docker-compose.yml and use docker-compose down in a cleanup script.
  2. Adding a health check and auto-remove: Configure containers to stop themselves after inactivity.
  3. Regular maintenance: Add a cron job to clean up old containers weekly.

Why This Matters Beyond Resources

Beyond wasting memory and CPU, these zombie containers can cause port conflicts (if servers bind to specific ports) and make your development environment unpredictable. They also represent a security concern—unattended services running that you might have forgotten about.

The core issue is that MCP tooling currently treats docker run like a regular subprocess, but Docker's architecture requires explicit lifecycle management. Until Anthropic adds better container lifecycle handling to Claude Code, the uvx approach is the most reliable fix.

Check your system today—you might be surprised at what's still running from last week's coding sessions.

AI Analysis

Claude Code users who run Docker-based MCP servers should immediately run `docker ps | grep mcp` to check for leaks. If you find containers, clean them up with `docker stop` and `docker rm`. For ongoing prevention, reconfigure your MCP servers to use `uvx` instead of Docker whenever possible. This requires finding the `uvx` package name for your MCP tools (often the same as the Docker image name without the registry prefix). Update your `claude_desktop_config.json` file to use the `uvx` command format. If a tool absolutely requires Docker, implement a cleanup routine. Consider writing a shell script that runs `docker ps --filter 'name=mcp' --format '{{.ID}}' | xargs -r docker rm -f` and scheduling it to run daily or adding it to your shell's logout/profile scripts. This is a temporary workaround until Claude Code improves its Docker process management.
Original sourcereddit.com

Trending Now

More in Products & Launches

View all