# Production Docker Compose for Proxmox MCP Server
# Uses Compose Specification format without deprecated version directive
services:
mcp-server:
build:
context: ..
dockerfile: docker/Dockerfile.prod
args:
BUILD_DATE: ${BUILD_DATE:-now}
VCS_REF: ${VCS_REF:-dev}
VERSION: ${VERSION:-latest}
image: proxmox-mcp-server:${IMAGE_TAG:-latest}
container_name: proxmox-mcp-server
restart: unless-stopped
ports:
- "0.0.0.0:8080:8080" # MCP server (internet accessible)
- "192.168.1.0/24:8081:8081" # Admin interface (local network only)
environment:
- MCP_HOST=0.0.0.0
- MCP_PORT=8080
- ADMIN_PORT=8081
- LOG_LEVEL=${LOG_LEVEL:-INFO}
- DEVICE_AUTH_ENABLED=true
# Proxmox configuration from environment
- SSH_TARGET=${SSH_TARGET}
- SSH_HOST=${SSH_HOST}
- SSH_USER=${SSH_USER}
- SSH_PORT=${SSH_PORT:-22}
- SSH_KEY_PATH=/app/keys/ssh_key
- PROXMOX_HOST=${PROXMOX_HOST}
- PROXMOX_USER=${PROXMOX_USER}
- PROXMOX_TOKEN_NAME=${PROXMOX_TOKEN_NAME}
- PROXMOX_TOKEN_VALUE=${PROXMOX_TOKEN_VALUE}
- PROXMOX_VERIFY_SSL=${PROXMOX_VERIFY_SSL:-false}
- ENABLE_PROXMOX_API=${ENABLE_PROXMOX_API:-true}
- ENABLE_DANGEROUS_COMMANDS=${ENABLE_DANGEROUS_COMMANDS:-false}
volumes:
- mcp_logs:/app/logs
- mcp_data:/app/data # Device authentication storage
- /opt/proxmox-mcp/keys:/app/keys:ro
- /opt/proxmox-mcp/config:/app/config:ro
networks:
- mcp-network
healthcheck:
test: ["CMD", "sh", "-c", "curl -f http://localhost:8080/health && curl -f http://localhost:8081/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp:noexec,nosuid,size=100m
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
caddy:
image: caddy:2-alpine
container_name: mcp-reverse-proxy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- /opt/proxmox-mcp/config/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
networks:
- mcp-network
depends_on:
mcp-server:
condition: service_healthy
logging:
driver: "json-file"
options:
max-size: "5m"
max-file: "3"
# Optional: Prometheus monitoring
prometheus:
image: prom/prometheus:latest
container_name: mcp-prometheus
restart: unless-stopped
ports:
- "127.0.0.1:9090:9090"
volumes:
- /opt/proxmox-mcp/monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
networks:
- mcp-network
profiles:
- monitoring
# Optional: Grafana dashboards
grafana:
image: grafana/grafana:latest
container_name: mcp-grafana
restart: unless-stopped
ports:
- "127.0.0.1:3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin}
volumes:
- grafana_data:/var/lib/grafana
- /opt/proxmox-mcp/monitoring/grafana:/etc/grafana/provisioning
networks:
- mcp-network
profiles:
- monitoring
networks:
mcp-network:
driver: bridge
name: mcp-network
ipam:
config:
- subnet: 172.20.0.0/16
driver_opts:
com.docker.network.bridge.enable_icc: "true"
com.docker.network.bridge.enable_ip_masquerade: "true"
com.docker.network.driver.mtu: "1500"
volumes:
mcp_logs:
name: mcp_logs
mcp_data:
name: mcp_data
caddy_data:
name: caddy_data
caddy_config:
name: caddy_config
prometheus_data:
name: prometheus_data
grafana_data:
name: grafana_data