Docker Compose для локального стенда: web + db + cache в одном файле
Тестируем Docker Compose - бывший Fig - для локального dev-окружения. Один docker-compose.yml вместо трёх страниц инструкций. Что работает, где пока трёт.
Docker Compose (бывший Fig) выходит как официальный инструмент оркестрации multi-container приложений
Несколько недель назад Docker Inc. официально объявила, что Fig становится Docker Compose - инструментом в составе официальной экосистемы. Мы с Fig поигрались ещё в конце 2014-го, поэтому когда вышел Compose, решили прогнать его на реальном проекте и посмотреть, стоит ли рекомендовать клиентам.
Контекст: есть небольшой веб-проект - Python/Django-приложение, PostgreSQL, Redis. Стандартный стек. Задача - чтобы разработчик поднял локальное окружение без пятиминутного созвона с DevOps и трёх страниц инструкций в вики.
Что было до
До этого жили примерно так. Вики-страница «Как поднять проект локально» содержала: установи PostgreSQL нужной версии, создай базу, прогони миграции, установи Redis, пропиши переменные окружения в .env, не забудь про virtualenv, проверь что порты не заняты. Семь пунктов, каждый с подпунктами.
Работало примерно так: старожилы проекта делали это на автопилоте, новые люди тратили час, иногда два, причём половина времени уходила на «у меня не та версия PostgreSQL» или «порт 5432 занят другим проектом».
docker-compose.yml
Файл получился такой:
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
links:
- db
- cache
env_file:
- .env
db:
image: postgres:9.3
environment:
POSTGRES_DB: myapp
POSTGRES_USER: myapp
POSTGRES_PASSWORD: localpass
cache:
image: redis:2.8
Сорок строк. Запускается через docker-compose up. Всё.
Через минуту-полторы (если образы уже скачаны) три контейнера поднимаются в правильном порядке: сначала db и cache, потом web. Django видит базу по имени хоста db, Redis - по cache. Переменные окружения берутся из .env, который не коммитится, а .env.example лежит в репозитории.
Что реально удобно
docker-compose up и docker-compose down. Это главное. Поднять всё окружение и убрать его без следов - одна команда. Никакого «убей процесс PostgreSQL, удали сокет, очисти tmp». docker-compose down останавливает контейнеры и убирает сеть.
Изоляция по проектам. Два проекта с разными версиями PostgreSQL живут на одной машине без конфликтов. Это решает ровно ту проблему, о которой написано выше.
volumes для кода. Директория проекта монтируется внутрь контейнера, Django видит изменения файлов напрямую - стандартный runserver с автоперезагрузкой работает как обычно. Не нужно пересобирать образ при каждом изменении кода.
Логи из одного места. docker-compose logs -f показывает потоки от всех трёх контейнеров вперемешку, с префиксом сервиса. Удобно отлаживать: видно что web-запрос пришёл, db выполнила запрос, redis ответил.
Где пока трёт
Не всё радужно. Несколько мест, где мы споткнулись.
Первый запуск медленный. Образы postgres:9.3 и redis:2.8 весят вместе около 300 МБ. На офисном интернете - минут пять. Для CI это приемлемо, для нового разработчика в первый рабочий день - немного обескураживает. Локальный registry решает проблему, но это уже отдельная инфраструктура.
Пересборка образа при изменении Dockerfile. docker-compose up не пересобирает образ автоматически если Dockerfile поменялся. Нужно явно docker-compose build. Люди забывают, получают старое окружение, тратят время на диагностику. Добавили в вики одно предупреждение, но лучше бы это поведение было очевиднее.
links как механизм сети. В текущей версии Compose сервисы видят друг друга через links. Это работает, но выглядит как временное решение: нужно явно прописывать зависимости, а не просто называть сервисы по имени. Docker сейчас активно меняет сетевую модель, и здесь явно будут изменения - приходится держать это в голове.
Данные не персистентны между down и up. docker-compose down убивает контейнеры вместе с данными базы. Для чистого локального стенда - это хорошо, для разработки где хочется сохранить тестовые данные - нужно монтировать volume явно. Мы добавили закомментированный блок в пример-конфиг с пояснением.
Итог для клиентов
Мы протестировали на одном проекте, добавили в общую инфраструктуру. В рамках интеграционных работ начинаем рекомендовать Docker Compose как стандартный способ описать локальное dev-окружение для новых проектов. Не для продакшна - там пока своя история. Именно для локальной разработки.
Три страницы вики свернулись в сорок строк YAML и один README с тремя командами. Новый разработчик поднял окружение за семь минут. Для нас это достаточный аргумент чтобы двигаться в этом направлении.