🐳 DevOps & Docker
Как Claude Code работает с Docker-контейнерами, WSL2, Caddy reverse proxy и инфраструктурой. Правила безопасности, MCP-инструменты и конфигурация для Windows Server 2025.
🔌 Docker через MCP (не через Bash)
На Windows с WSL2 прямые docker команды из Claude Code часто не работают из-за PATH. Кроме того, Bash hook в настройках блокирует их явно. Правило: всегда использовать mcp__docker__* инструменты.
💡
Почему MCP, а не Bash? MCP docker-инструменты используют Docker SDK напрямую, минуя shell. Это безопаснее, предсказуемее и не зависит от PATH. Bash hook (bash-mcp-guard.cjs) перехватит любой docker exec и предложит альтернативу.
❌ НЕТ Bash команды
docker exec -it backend-1 php artisan route:list
docker logs -f backend-1
docker compose ps
✅ ДА MCP инструменты
mcp__docker__docker_exec
container: "backend-1"
command: "php artisan route:list"
mcp__docker__docker_container_logs
container: "backend-1"
mcp__docker__docker_compose_ps
path: "E:/Clients/project"
Полный справочник Docker MCP инструментов
| MCP инструмент | Аналог docker команды | Когда использовать |
docker_exec | docker exec -it | Запуск команд внутри контейнера |
docker_container_logs | docker logs | Просмотр логов контейнера |
docker_list_containers | docker ps -a | Список всех контейнеров |
docker_inspect_container | docker inspect | Детальная информация о контейнере |
docker_container_stats | docker stats | CPU/RAM использование |
docker_start_container | docker start | Запустить остановленный контейнер |
docker_stop_container | docker stop | Остановить контейнер |
docker_restart_container | docker restart | Перезапустить контейнер |
docker_compose_ps | docker compose ps | Статус compose-стека |
docker_compose_logs | docker compose logs | Логи всего стека |
docker_compose_up | docker compose up -d | Запуск стека |
docker_compose_down | docker compose down | Остановка стека |
docker_compose_restart | docker compose restart | Перезапуск сервиса в стеке |
docker_list_images | docker images | Список образов |
docker_create_network | docker network create | Создать сеть |
docker_list_networks | docker network ls | Список сетей |
⚙️ Подключение Docker MCP
Docker MCP добавляется в глобальный settings.local.json (не в per-project .mcp.json, т.к. нужен везде):
// ~/.claude/settings.local.json
{
"mcpServers": {
"docker": {
"command": "npx",
"args": ["-y", "docker-mcp@latest"]
},
"ruflo": {
"command": "npx",
"args": ["-y", "ruflo@latest"]
}
}
}
⚠️
Требуется Docker Desktop — должен быть запущен с WSL2 backend. MCP подключается через Docker socket. Если получаешь ошибку connection refused — проверь статус Docker Desktop.
🖥️ WSL2 — настройка памяти
На Windows Server 2025 с 47 GB RAM конфигурация WSL2 критична для Docker. OOM убивал PostgreSQL при ETL-операциях — решение зафиксировано.
# C:\Users\Администратор\.wslconfig
# Применить: wsl --shutdown (потом перезапустить Docker Desktop)
[wsl2]
memory=38GB # 80% от 47GB — Windows-хосту остаётся 9GB
swap=2GB # Большой swap маскирует OOM и замедляет работу
localhostForwarding=true
[experimental]
hostAddressLoopback=true # Контейнеры видят host.docker.internal
✅
Правило памяти: WSL2 = 80% RAM. Swap = минимальный (2GB). Большой swap создаёт иллюзию достаточности памяти, но приводит к деградации производительности.
🌐 Caddy Reverse Proxy
Все публичные домены проксируются через Caddy. Caddy — единственный сервис, занимающий порты 80/443. Никакой другой контейнер не биндится на эти порты.
Расположение и управление
# Папка прокси
E:\Clients\Windows\proxy\
# CLI управление (PowerShell)
proxy.cmd list # Текущие маршруты + TLS даты
proxy.cmd add site.ru container-name:80 # Добавить домен
proxy.cmd connect my-network # Подключить Caddy к сети сайта
proxy.cmd backup # Архив + сертификаты LE
Текущая маршрутизация
| Домен | Upstream |
| phone.rosveb.ru | phone-rosveb-ru-frontend-1:3000
/api/* → phone-rosveb-ru-backend-1:8000 |
| massage.rosveb.ru | project-nginx-1:80 |
| dev.gulaev.ru | gulaev-nginx:80 |
| notal.rosveb.ru | notal-nginx:80 |
| gis.rosveb.ru | catalog_nginx:80 |
Добавление нового сайта — чек-лист
# 1. Подключить Caddy к сети сайта
proxy connect <имя-docker-сети>
# 2. Добавить маршрутизацию
proxy add new-site.example.ru container-name:80
# 3. Адаптация приложения под reverse proxy:
# Laravel — в AppServiceProvider или bootstrap/app.php:
URL::forceScheme(request()->isSecure() ? 'https' : 'http');
# + TrustProxies middleware с указанием Caddy IP
# Next.js / Nuxt:
NEXT_PUBLIC_SITE_URL=https://new-site.example.ru
# FastAPI:
uvicorn main:app --proxy-headers --forwarded-allow-ips='*'
🚫
НЕ публиковать порты 80/443 в docker-compose.yml для своих сервисов — они заняты Caddy. Dev-доступ — только через свободные порты из PORTS.md (например :8011).
📋 Docker Compose — лучшие практики
Шаблон compose для Laravel-проекта
# docker-compose.yml
services:
backend:
build: .
container_name: my-project-backend-1
networks:
- internal
- proxy # Caddy видит этот контейнер
environment:
- APP_ENV=production
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
container_name: my-project-db-1
volumes:
- pg_data:/var/lib/postgresql/data
networks:
- internal # ТОЛЬКО внутренняя сеть, не proxy!
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
networks:
internal:
proxy:
external: true # Создана через proxy connect
volumes:
pg_data:
💡
Именование контейнеров: используй паттерн <проект>-<сервис>-1. Это совпадает с автоматическим именованием Compose и важно для Caddy, который обращается по имени через embedded DNS.
⚡ Выполнение команд внутри контейнеров
Laravel Artisan через Docker MCP
// Вместо: docker exec -it backend-1 php artisan migrate
// Использовать MCP инструмент:
mcp__docker__docker_exec({
container: "phone-rosveb-ru-backend-1",
command: "php artisan migrate --force"
})
// Очередь (queue worker) — проверить статус:
mcp__docker__docker_exec({
container: "phone-rosveb-ru-backend-1",
command: "php artisan queue:work --once"
})
⚠️
laravel-boost MCP предоставляет специализированные инструменты для Laravel: роуты, модели, события — напрямую через MCP без docker exec. Предпочитать его для Laravel-специфичных операций.
Python / FastAPI команды
mcp__docker__docker_exec({
container: "python-etl-app-1",
command: "alembic upgrade head" // Миграции
})
mcp__docker__docker_exec({
container: "python-etl-app-1",
command: "python -m pytest tests/ -v" // Тесты
})
❤️ Health Checks и мониторинг
// Проверить здоровье всех контейнеров:
mcp__docker__docker_container_health_check({ container: "backend-1" })
// CPU/RAM статистика:
mcp__docker__docker_container_stats({ container: "backend-1" })
// Inspect — сети, порты, env (без secrets):
mcp__docker__docker_inspect_container({ container: "backend-1" })
Признаки OOM и решение
| Симптом | Диагноз | Решение |
| Контейнер перезапускается сам | OOM killer | Уменьшить shared_buffers в PG, увеличить WSL2 memory |
Exit code 137 | SIGKILL от OOM | Снизить max_parallel_workers в PG |
| Медленные запросы при ETL | Swap активен | Снизить work_mem, добавить батчинг |
| PG не стартует | shared_buffers > 25% WSL2 | ALTER SYSTEM SET shared_buffers = '4GB' |
🔒 Безопасность контейнеров
# Никогда не делать в docker-compose:
ports:
- "5432:5432" # PostgreSQL напрямую в интернет!
- "6379:6379" # Redis без аутентификации!
# Правильно — только внутренние сети:
networks:
- internal # Только для межсервисного общения
# БД не имеет секции ports вообще
🚫
critical-files-guard.cjs блокирует изменение docker-compose.production.yml. Для редактирования — установить переменную CONFIRM_CRITICAL=yes или изменить вручную.