# Docker Deployment Guide for Portainer MCP Servers This guide covers how to build and run the Portainer MCP servers using Docker containers. ## Prerequisites - Docker Engine 20.10+ - Docker Compose 2.0+ - Portainer Business Edition instance - Valid Portainer API key ## Quick Start 1. **Clone the repository** ```bash git clone https://github.com/yourusername/portainer-mcp.git cd portainer-mcp ``` 2. **Create environment file** ```bash cp .env.example .env # Edit .env with your Portainer credentials nano .env # or use your preferred editor ``` 3. **Pull images (or build locally)** ```bash # Option A: Pull from registry (recommended) docker-compose pull # Option B: Build locally ./build-docker.sh all ``` 4. **Start all services** ```bash docker-compose up -d ``` ## Individual Container Management ### Building Containers Build all containers: ```bash ./build-docker.sh all ``` Build specific container: ```bash ./build-docker.sh core ./build-docker.sh docker ./build-docker.sh kubernetes # etc... ``` ### Running Containers Run all services: ```bash docker-compose up -d ``` Run specific service: ```bash docker-compose up -d portainer-core docker-compose up -d portainer-docker # etc... ``` View logs: ```bash docker-compose logs -f portainer-core docker-compose logs -f portainer-docker # etc... ``` Stop services: ```bash docker-compose down ``` ## Container Details Each MCP server runs in its own container with the following configuration: | Service | Container Name | Port | Purpose | |---------|---------------|------|---------| | portainer-core | portainer-mcp-core | 3000 | User management, teams, RBAC | | portainer-environments | portainer-mcp-environments | 3001 | Environment management | | portainer-docker | portainer-mcp-docker | 3002 | Docker operations | | portainer-kubernetes | portainer-mcp-kubernetes | 3003 | Kubernetes management | | portainer-stacks | portainer-mcp-stacks | 3004 | Stack deployment | | portainer-edge | portainer-mcp-edge | 3005 | Edge computing | | portainer-gitops | portainer-mcp-gitops | 3006 | GitOps automation | ## Environment Variables All containers use a shared `.env` file for configuration. The docker-compose.yml file is configured to automatically load environment variables from this file using the `env_file` directive. ```yaml # docker-compose.yml snippet services: portainer-core: image: git.oe74.net/adelorenzo/portainer-mcp/portainer-core:latest env_file: - .env ``` See `.env.example` for a complete list of available environment variables with detailed documentation and troubleshooting tips. ### Key Variables: - `PORTAINER_URL` - Your Portainer instance URL (required) - `PORTAINER_API_KEY` - Your Portainer API token (required) - `PORTAINER_INSECURE` - Set to true for self-signed certificates - `HTTP_TIMEOUT` - Request timeout in seconds - `MAX_RETRIES` - Number of retry attempts ## Docker Compose Configuration The `docker-compose.yml` file defines all services with: - Individual port mappings - Shared environment variables - Automatic restart policies - Isolated network for inter-container communication ## Production Deployment For production environments, consider: 1. **Use Docker Swarm or Kubernetes** ```bash # Deploy as stack in Swarm docker stack deploy -c docker-compose.yml portainer-mcp ``` 2. **Enable health checks** Add to each service in docker-compose.yml: ```yaml healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 ``` 3. **Use secrets for API keys** ```yaml secrets: portainer_api_key: external: true ``` 4. **Configure resource limits** ```yaml deploy: resources: limits: cpus: '0.5' memory: 256M ``` ## Troubleshooting ### Container won't start - Check logs: `docker-compose logs portainer-` - Verify environment variables in `.env` - Ensure Portainer URL is accessible from container ### Connection errors - For self-signed certificates, set `PORTAINER_INSECURE=true` - Check network connectivity: `docker exec portainer-mcp-core curl https://your-portainer-url` ### Permission errors - Verify API key has required permissions - Check Portainer RBAC settings ## Security Considerations 1. **Never commit `.env` file** - It contains sensitive credentials 2. **Use read-only mounts** where possible 3. **Run containers as non-root user** (already configured) 4. **Enable TLS** for MCP connections in production 5. **Regularly update** base images and dependencies ## Advanced Configuration ### Custom Network ```yaml networks: portainer-mcp: driver: bridge ipam: config: - subnet: 172.20.0.0/16 ``` ### Volume Mounts For persistent logs or configuration: ```yaml volumes: - ./logs:/app/logs - ./config:/app/config:ro ``` ### Multi-stage Builds The Dockerfiles use single-stage builds for simplicity. For smaller images: ```dockerfile FROM python:3.11-slim AS builder # Build stage... FROM python:3.11-slim # Runtime stage... ``` ## Integration with Claude Desktop Since MCP uses stdio for communication, connecting Claude Desktop to Docker containers requires special configuration. ### Method 1: Docker Exec (Recommended) This method executes the Python script in an already-running container: ```json { "mcpServers": { "portainer-core": { "command": "docker", "args": ["exec", "-i", "portainer-mcp-core", "python", "portainer_core_server.py"] }, "portainer-environments": { "command": "docker", "args": ["exec", "-i", "portainer-mcp-environments", "python", "portainer_environments_server.py"] }, "portainer-docker": { "command": "docker", "args": ["exec", "-i", "portainer-mcp-docker", "python", "portainer_docker_server.py"] }, "portainer-kubernetes": { "command": "docker", "args": ["exec", "-i", "portainer-mcp-kubernetes", "python", "portainer_kubernetes_server.py"] }, "portainer-stacks": { "command": "docker", "args": ["exec", "-i", "portainer-mcp-stacks", "python", "portainer_stacks_server.py"] }, "portainer-edge": { "command": "docker", "args": ["exec", "-i", "portainer-mcp-edge", "python", "portainer_edge_server.py"] }, "portainer-gitops": { "command": "docker", "args": ["exec", "-i", "portainer-mcp-gitops", "python", "portainer_gitops_server.py"] } } } ``` **Prerequisites:** 1. Containers must be running: `docker-compose up -d` 2. Docker must be accessible from where Claude Desktop runs ### Method 2: Docker Run (Alternative) This method creates a new container for each MCP session: ```json { "mcpServers": { "portainer-core": { "command": "docker", "args": [ "run", "--rm", "-i", "--env-file", "/path/to/portainer-mcp/.env", "--network", "portainer-mcp_portainer-mcp", "git.oe74.net/adelorenzo/portainer-mcp/portainer-core:latest" ] } // ... similar for other servers } } ``` **Pros:** Doesn't require pre-running containers **Cons:** Slower startup, creates new container each time ### Important Notes - The `-i` flag is **required** for stdio communication - Ensure Docker daemon is running and accessible - For Windows/Mac users, Docker Desktop must be running - Container names must match those in docker-compose.yml ## Monitoring Monitor container health and resource usage: ```bash # View resource usage docker stats # Check container health docker ps --format "table {{.Names}}\t{{.Status}}" # Export metrics docker-compose ps --format json ```