Skip to content

Latest commit

 

History

History
483 lines (362 loc) · 21.2 KB

local-dev-docker-setup.md

File metadata and controls

483 lines (362 loc) · 21.2 KB

Локальная разработка с Docker

Документ описывает настройку и использование Docker для локальной разработки с поддержкой hot-reload.

Обзор

Система поддерживает два режима работы:

  • Development режим - с hot-reload, volumes для исходного кода, dev команды
  • Production режим - оптимизированные образы, без hot-reload

Быстрый старт

1. Подготовка окружения

# Скопируйте файл с переменными окружения
cp env.docker.example .env

# Скопируйте override файл для dev режима
cp docker-compose.override.yml.example docker-compose.override.yml

# При необходимости отредактируйте .env и docker-compose.override.yml

2. Запуск в Development режиме

# Запустить все сервисы с hot-reload
docker-compose up

# Или в фоновом режиме
docker-compose up -d

# Просмотр логов
docker-compose logs -f

# Логи конкретного сервиса
docker-compose logs -f experiment-service

3. Запуск в Production режиме

# Запустить без override файла (production образы)
docker-compose -f docker-compose.yml up

# Или временно переименовать override файл
mv docker-compose.override.yml docker-compose.override.yml.bak
docker-compose up

Миграции БД

Сервисы не применяют миграции при старте приложения. Вместо этого в docker-compose.yml есть одноразовые (one-shot) init-контейнеры: каждый выполняет python -m bin.migrate, применяет SQL-файлы из migrations/ своего сервиса и завершается. Рантайм-сервис ждёт успешного завершения своего init-контейнера (condition: service_completed_successfully), поэтому API стартует только после того, как применены все миграции, лежащие в образе.

Каталог migrations/ копируется в образ при сборке, а docker-compose up и make dev-up образы не пересобирают. Если после git pull или вашей правки появились новые SQL-файлы, поднимайте стек с пересборкой: docker-compose up -d --build. Иначе init-контейнер проверит старый список миграций, завершится успешно, и API стартует без новой схемы. make dev-rebuild для этого не подходит: он не пересобирает образы *-migrate и script-service.

Init-контейнер База Блокирует старт
auth-migrate auth_db auth-service
config-migrate config_db config-service
experiment-migrate experiment_db experiment-service
telemetry-ingest-migrate experiment_db telemetry-ingest-service
script-migrate script_db script-service

telemetry-ingest-migrate пишет в ту же experiment_db и общую таблицу schema_migrations, поэтому запускается строго после experiment-migrate.

script-service вдобавок применяет миграции сам при старте, поэтому повторный прогон после script-migrate печатает No pending migrations. Так же устроен продакшен (см. deployment-yandex-cloud.md).

Миграции идемпотентны: повторный прогон на актуальной схеме печатает No pending migrations.

Проверка и повторный прогон

# Логи init-контейнера (успешный прогон заканчивается "Applied N migration(s)."
# или "No pending migrations.")
docker-compose logs auth-migrate
docker-compose logs experiment-migrate

# Повторно применить миграции, например после добавления нового SQL-файла.
# Каталог migrations/ копируется в образ при сборке и не монтируется в контейнер,
# поэтому без --build новый файл не будет виден и прогон скажет "No pending migrations."
docker-compose run --rm --build experiment-migrate
docker-compose run --rm --build telemetry-ingest-migrate
docker-compose run --rm --build script-migrate

Если init-контейнер упал, зависящий от него сервис не стартует: смотрите логи init-контейнера, исправьте миграцию или DATABASE_URL и перезапустите стек с пересборкой (docker-compose up -d --build): без неё init-контейнер снова прогонит старый SQL из образа.

Make-таргеты

make help выводит команды с описаниями, взятыми из ##-комментариев рядом с целями Makefile. Для просмотра справки Docker, Poetry и Node.js не требуются. Обычный make сохраняет прежнее поведение — запускает make test.

Длинные команды Makefile реализованы в scripts/backend.sh, scripts/frontend.sh, scripts/dev.sh и scripts/firmware-coverage.sh. Общие функции поиска Python и подготовки тестового PostgreSQL находятся в scripts/dev-common.sh. Запускайте команды через Makefile: он передаёт настройки и выполняет зависимости.

make backend-install PYTHON=/path/to/python3.14
make test-backend TEST_POSTGRESQL_DSN='postgresql://user:pass@localhost:5433/postgres'
make test-coverage-backend  # тот же поиск порта/учётных данных и ожидание PostgreSQL
make test-deploy-contract  # проверки shell-команд и production-контракта

Python выбирается один раз до перехода в директории компонентов. При заданном TEST_POSTGRESQL_DSN тесты используют его без запуска Docker; иначе контейнер TimescaleDB должен успешно запуститься и пройти проверку готовности. Ошибки установки зависимостей, запуска БД и тестов возвращают ненулевой код.

Очистка dev-окружения ограничена основным Compose-проектом и отдельно запущенным проектом infrastructure/logging; фильтры по общим именам контейнеров и глобальный docker image prune не используются:

  • make dev-fix пересоздаёт контейнеры и запускает стек, сохраняя данные. В отличие от прежней реализации, PostgreSQL volume автоматически не удаляется.
  • make dev-clean выполняет down -v --remove-orphans для обоих проектов; удаляются их контейнеры и volumes, включая PostgreSQL, MinIO и логи.
  • make dev-clean-all дополнительно удаляет локально собранные образы этих проектов (--rmi local).

Make-таргеты выполняют python -m bin.migrate внутри уже запущенного рантайм-контейнера (docker-compose exec), поэтому нужны, когда стек уже поднят. Они видят те миграции, что были в образе на момент сборки: после добавления SQL-файла сначала пересоберите этот сервис: docker-compose up -d --build <service>, например experiment-service для make experiment-migrate или script-service для make script-migrate.

make auth-migrate              # auth_db
make experiment-migrate        # experiment_db
make telemetry-ingest-migrate  # experiment_db (после experiment-migrate)
make config-migrate            # config_db
make script-migrate            # script_db
make auth-init                 # создать auth_db + миграции + первый админ

Список ожидающих миграций без применения: добавьте --dry-run, например docker-compose run --rm --build experiment-migrate python -m bin.migrate --dry-run.

Архитектура Hot-Reload

Auth Service (Python/aiohttp)

Инструмент: watchfiles (настроен в docker-compose.override.yml)

Как работает:

  1. Исходный код монтируется через volume из ./projects/backend/services/auth-service/src
  2. watchfiles отслеживает изменения .py файлов в ./src
  3. При изменении автоматически перезапускается процесс python -m auth_service.main

Команда запуска:

watchfiles --filter python 'python -m auth_service.main' ./src

Проверка работы:

  1. Откройте файл projects/backend/services/auth-service/src/auth_service/main.py
  2. Внесите изменение (например, добавьте комментарий)
  3. Сохраните файл
  4. В логах docker-compose logs -f auth-service должно появиться сообщение о перезапуске

Experiment Service (Python/aiohttp)

Инструмент: watchfiles (настроен в docker-compose.override.yml)

Как работает:

  1. Исходный код монтируется через volume из ./projects/backend/services/experiment-service/src
  2. watchfiles отслеживает изменения .py файлов в ./src
  3. При изменении автоматически перезапускается процесс python -m experiment_service.main

Команда запуска:

watchfiles 'python -m experiment_service.main' ./src

Проверка работы:

  1. Откройте файл projects/backend/services/experiment-service/src/experiment_service/main.py
  2. Внесите изменение (например, добавьте комментарий)
  3. Сохраните файл
  4. В логах docker-compose logs -f experiment-service должно появиться сообщение о перезапуске

Auth Proxy (Node.js/Fastify)

Инструмент: ts-node-dev

Как работает:

  1. Исходный код монтируется через volume из ./projects/frontend/apps/auth-proxy/src
  2. ts-node-dev компилирует TypeScript на лету и отслеживает изменения
  3. При изменении автоматически перезапускает процесс

Команда запуска:

npm run dev  # выполняет: ts-node-dev --respawn --transpile-only src/index.ts

Проверка работы:

  1. Откройте файл projects/frontend/apps/auth-proxy/src/index.ts
  2. Внесите изменение
  3. Сохраните файл
  4. В логах должно появиться сообщение о перезапуске

Experiment Portal (React/Vite)

Инструмент: Vite HMR (Hot Module Replacement)

Как работает:

  1. Исходный код монтируется через volumes
  2. Vite dev server запускается на порту 3000
  3. Vite отслеживает изменения и применяет их через HMR (без полной перезагрузки страницы)

Команда запуска:

npm run dev  # выполняет: vite

Проверка работы:

  1. Откройте браузер на http://localhost:3000
  2. Откройте файл компонента, например projects/frontend/apps/experiment-portal/src/pages/ExperimentsList.tsx
  3. Внесите изменение (например, измените текст)
  4. Сохраните файл
  5. Изменения должны появиться в браузере без перезагрузки страницы

Структура Dockerfile'ов

Multi-stage Build

Все Dockerfile'ы используют multi-stage build для оптимизации:

Auth Service

  • Base stage: Установка зависимостей через Poetry
  • Production: Запуск приложения

Experiment Service

  • Base stage: Установка зависимостей через Poetry
  • Production: Запуск приложения

Auth Proxy

  • Base stage: Установка зависимостей
  • Development stage: Запуск с ts-node-dev для hot-reload
  • Build stage: Компиляция TypeScript
  • Production stage: Минимальный runtime образ

Experiment Portal

  • Development stage: Запуск Vite dev server
  • Build stage: Сборка React приложения
  • Production stage: Nginx для статических файлов

Docker Compose Override

Файл docker-compose.override.yml автоматически загружается Docker Compose и переопределяет настройки из основного docker-compose.yml.

Что переопределяется:

  1. Volumes - монтирование исходного кода для hot-reload
  2. Commands - использование dev команд вместо production
  3. Build targets - использование development stages из Dockerfile'ов
  4. Environment variables - установка DEV_MODE=true, NODE_ENV=development
  5. Ports - дополнительные порты для отладки

Пример использования:

# docker-compose.override.yml
services:
  experiment-service:
    volumes:
      - ./projects/backend/services/experiment-service/src:/app/src:ro
    command: watchfiles 'python -m experiment_service.main' --filter python ./src

Troubleshooting

Hot-reload не работает

Проблема: Изменения в коде не применяются автоматически

Решения:

  1. Проверьте, что docker-compose.override.yml существует и правильно настроен
  2. Убедитесь, что volumes правильно монтированы:
    docker-compose exec experiment-service ls -la /app/src
  3. Проверьте логи на наличие ошибок:
    docker-compose logs experiment-service
  4. Для Python: убедитесь, что watchfiles установлен:
    docker-compose exec experiment-service pip list | grep watchfiles

Порты уже заняты

Проблема: Error: bind: address already in use

Решения:

  1. Измените порты в docker-compose.override.yml:
    ports:
      - "8003:8002"  # вместо 8002:8002
  2. Или остановите процесс, использующий порт:
    # Linux/Mac
    lsof -ti:8002 | xargs kill -9
    
    # Windows
    netstat -ano | findstr :8002
    taskkill /PID <PID> /F

Изменения не видны в контейнере

Проблема: Файлы изменены на хосте, но не видны в контейнере

Решения:

  1. Проверьте правильность путей в volumes:
    volumes:
      - ./projects/backend/services/experiment-service/src:/app/src  # правильный путь
      # НЕ: - ./src:/app/src  (относительно compose файла)
  2. Убедитесь, что файлы сохранены на диске
  3. Перезапустите контейнер:
    docker-compose restart experiment-service

Медленная работа hot-reload

Проблема: Hot-reload работает, но очень медленно

Решения:

  1. Используйте .dockerignore для исключения ненужных файлов
  2. Исключите большие директории из volumes:
    volumes:
      - /app/node_modules  # исключить node_modules
      - /app/__pycache__   # исключить Python кэш
  3. Для Windows/Mac используйте Docker Desktop с настроенным file sharing

Ошибки при сборке образов

Проблема: docker-compose build завершается с ошибкой

Решения:

  1. Очистите кэш Docker:
    docker-compose build --no-cache
  2. Проверьте, что все зависимости установлены:
    # Для Python
    cd projects/backend/services/experiment-service
    poetry install
    
    # Для Node.js (общий npm workspace, из корня репозитория)
    npm ci
  3. Проверьте версии в Dockerfile (Node.js, Python)

Полезные команды

Управление контейнерами

# Запуск всех сервисов
docker-compose up -d

# Остановка всех сервисов
docker-compose stop

# Остановка и удаление контейнеров
docker-compose down

# Пересборка образов
docker-compose build

# Пересборка без кэша
docker-compose build --no-cache

# Перезапуск конкретного сервиса
docker-compose restart experiment-service

Работа с логами

# Все логи
docker-compose logs -f

# Логи конкретного сервиса
docker-compose logs -f experiment-service
docker-compose logs -f auth-service
docker-compose logs -f auth-proxy

# Последние 100 строк
docker-compose logs --tail=100 experiment-service
docker-compose logs --tail=100 auth-service

Выполнение команд в контейнере

# Запуск shell в контейнере
docker-compose exec experiment-service sh

# Выполнение команды
docker-compose exec experiment-service python -m pytest

# Выполнение команды в новом контейнере
docker-compose run --rm experiment-service python -m pytest

Работа с базой данных

# Подключение к PostgreSQL (порт 5433 на хосте)
docker-compose exec postgres psql -U postgres -d experiment_db
docker-compose exec postgres psql -U postgres -d auth_db

# Или с хоста (если установлен psql)
psql -h localhost -p 5433 -U postgres -d experiment_db
psql -h localhost -p 5433 -U postgres -d auth_db

Миграции применяются init-контейнерами при старте стека; после появления новых SQL-файлов поднимайте его с --build, см. Миграции БД.

Очистка

# Удаление контейнеров и volumes
docker-compose down -v

# Удаление всех образов проекта
docker-compose down --rmi all

# Полная очистка (контейнеры, образы, volumes, сети)
docker-compose down -v --rmi all

Переменные окружения

Основные переменные окружения описаны в env.docker.example.

Для development режима важны:

  • DEV_MODE=true - включение dev режима
  • NODE_ENV=development - для Node.js сервисов
  • ENV=development - для Python сервисов

Следующие шаги

После настройки hot-reload можно:

  1. Настроить отладку через IDE (VS Code, PyCharm)
  2. Настроить интеграционные тесты в Docker
  3. Добавить дополнительные сервисы (Redis, RabbitMQ) при необходимости
  4. Настроить мониторинг и логирование

Дополнительные ресурсы