Документ описывает настройку и использование Docker для локальной разработки с поддержкой hot-reload.
Система поддерживает два режима работы:
- Development режим - с hot-reload, volumes для исходного кода, dev команды
- Production режим - оптимизированные образы, без hot-reload
# Скопируйте файл с переменными окружения
cp env.docker.example .env
# Скопируйте override файл для dev режима
cp docker-compose.override.yml.example docker-compose.override.yml
# При необходимости отредактируйте .env и docker-compose.override.yml# Запустить все сервисы с hot-reload
docker-compose up
# Или в фоновом режиме
docker-compose up -d
# Просмотр логов
docker-compose logs -f
# Логи конкретного сервиса
docker-compose logs -f experiment-service# Запустить без 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 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.
Инструмент: watchfiles (настроен в docker-compose.override.yml)
Как работает:
- Исходный код монтируется через volume из
./projects/backend/services/auth-service/src watchfilesотслеживает изменения.pyфайлов в./src- При изменении автоматически перезапускается процесс
python -m auth_service.main
Команда запуска:
watchfiles --filter python 'python -m auth_service.main' ./srcПроверка работы:
- Откройте файл
projects/backend/services/auth-service/src/auth_service/main.py - Внесите изменение (например, добавьте комментарий)
- Сохраните файл
- В логах
docker-compose logs -f auth-serviceдолжно появиться сообщение о перезапуске
Инструмент: watchfiles (настроен в docker-compose.override.yml)
Как работает:
- Исходный код монтируется через volume из
./projects/backend/services/experiment-service/src watchfilesотслеживает изменения.pyфайлов в./src- При изменении автоматически перезапускается процесс
python -m experiment_service.main
Команда запуска:
watchfiles 'python -m experiment_service.main' ./srcПроверка работы:
- Откройте файл
projects/backend/services/experiment-service/src/experiment_service/main.py - Внесите изменение (например, добавьте комментарий)
- Сохраните файл
- В логах
docker-compose logs -f experiment-serviceдолжно появиться сообщение о перезапуске
Инструмент: ts-node-dev
Как работает:
- Исходный код монтируется через volume из
./projects/frontend/apps/auth-proxy/src ts-node-devкомпилирует TypeScript на лету и отслеживает изменения- При изменении автоматически перезапускает процесс
Команда запуска:
npm run dev # выполняет: ts-node-dev --respawn --transpile-only src/index.tsПроверка работы:
- Откройте файл
projects/frontend/apps/auth-proxy/src/index.ts - Внесите изменение
- Сохраните файл
- В логах должно появиться сообщение о перезапуске
Инструмент: Vite HMR (Hot Module Replacement)
Как работает:
- Исходный код монтируется через volumes
- Vite dev server запускается на порту 3000
- Vite отслеживает изменения и применяет их через HMR (без полной перезагрузки страницы)
Команда запуска:
npm run dev # выполняет: viteПроверка работы:
- Откройте браузер на
http://localhost:3000 - Откройте файл компонента, например
projects/frontend/apps/experiment-portal/src/pages/ExperimentsList.tsx - Внесите изменение (например, измените текст)
- Сохраните файл
- Изменения должны появиться в браузере без перезагрузки страницы
Все Dockerfile'ы используют multi-stage build для оптимизации:
- Base stage: Установка зависимостей через Poetry
- Production: Запуск приложения
- Base stage: Установка зависимостей через Poetry
- Production: Запуск приложения
- Base stage: Установка зависимостей
- Development stage: Запуск с
ts-node-devдля hot-reload - Build stage: Компиляция TypeScript
- Production stage: Минимальный runtime образ
- Development stage: Запуск Vite dev server
- Build stage: Сборка React приложения
- Production stage: Nginx для статических файлов
Файл docker-compose.override.yml автоматически загружается Docker Compose и переопределяет настройки из основного docker-compose.yml.
- Volumes - монтирование исходного кода для hot-reload
- Commands - использование dev команд вместо production
- Build targets - использование development stages из Dockerfile'ов
- Environment variables - установка
DEV_MODE=true,NODE_ENV=development - 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Проблема: Изменения в коде не применяются автоматически
Решения:
- Проверьте, что
docker-compose.override.ymlсуществует и правильно настроен - Убедитесь, что volumes правильно монтированы:
docker-compose exec experiment-service ls -la /app/src - Проверьте логи на наличие ошибок:
docker-compose logs experiment-service
- Для Python: убедитесь, что
watchfilesустановлен:docker-compose exec experiment-service pip list | grep watchfiles
Проблема: Error: bind: address already in use
Решения:
- Измените порты в
docker-compose.override.yml:ports: - "8003:8002" # вместо 8002:8002
- Или остановите процесс, использующий порт:
# Linux/Mac lsof -ti:8002 | xargs kill -9 # Windows netstat -ano | findstr :8002 taskkill /PID <PID> /F
Проблема: Файлы изменены на хосте, но не видны в контейнере
Решения:
- Проверьте правильность путей в volumes:
volumes: - ./projects/backend/services/experiment-service/src:/app/src # правильный путь # НЕ: - ./src:/app/src (относительно compose файла)
- Убедитесь, что файлы сохранены на диске
- Перезапустите контейнер:
docker-compose restart experiment-service
Проблема: Hot-reload работает, но очень медленно
Решения:
- Используйте
.dockerignoreдля исключения ненужных файлов - Исключите большие директории из volumes:
volumes: - /app/node_modules # исключить node_modules - /app/__pycache__ # исключить Python кэш
- Для Windows/Mac используйте Docker Desktop с настроенным file sharing
Проблема: docker-compose build завершается с ошибкой
Решения:
- Очистите кэш Docker:
docker-compose build --no-cache
- Проверьте, что все зависимости установлены:
# Для Python cd projects/backend/services/experiment-service poetry install # Для Node.js (общий npm workspace, из корня репозитория) npm ci
- Проверьте версии в 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 можно:
- Настроить отладку через IDE (VS Code, PyCharm)
- Настроить интеграционные тесты в Docker
- Добавить дополнительные сервисы (Redis, RabbitMQ) при необходимости
- Настроить мониторинг и логирование