Использование Docker для разработки Rails

Использование Docker для разработки Rails

Содержание
  1. Уровень 0: просто запустить приложение на docker
  2. Уровень 1: добавьте несколько конфигураций качества жизни для разработчиков
  3. Уровень 2: добавление возможности повторного использования и sidekiq

Недавно мне поручили старый проект, и хотя, к счастью, в Read.me были инструкции по его локальной настройке, количество шагов было чертовски велико. Поэтому вместо того, чтобы потратить полдня на их выполнение, я потратил 2 дня на их автоматизацию (будущие разработчики скажут мне спасибо… возможно).
Я хотел максимально приблизиться к настройке локального env одной командой.

Чтобы упростить процесс, как вы уже догадались из названия статьи, я решил настроить docker и docker-compose. Я начал с примера конфигурации из awesome-compose.

Уровень 0: просто запустить приложение на docker

FROM ruby:2.6.5 WORKDIR /myapp COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock RUN bundle install COPY . /myapp COPY config/database.yml.example /myapp/config/database.yml CMD bundle exec rails s -p 8080 -b '0.0.0.0'

Я не буду сильно вдаваться в подробности, основная концепция такова:

сначала копируем только gem-файлы и устанавливаем gems (это делается для того, чтобы воспользоваться преимуществами механизма кэширования при сборке образов для ускорения пересборки) копируем остальной код приложения Создаем файл конфигурации для базы данных на основе шаблона (детали будут передаваться через переменные ENV)

Поскольку на этот раз целью являются локальные разработки, компиляция активов не является проблемой, которую мы хотим оптимизировать.

Далее, маэстро организует локальный env: docker-compose

services: db: image: postgres volumes: - ./tmp/db:/var/lib/postgresql/data environment: POSTGRES_PASSWORD: пароль web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" ports: - "3000:3000" environment: POSTGRES_HOST: db REDIS_URL: redis://redis REDIS_HOST: redis depends_on: - db - redis redis: image: 'redis:5-alpine' команда: redis-server

Большая часть этого - благодаря помощи awesome-compose. Чего мы хотим добиться:

Запустить наше приложение вместе с базой данных postgres и сервером redis Чтобы данные базы postgres сохранялись Использовать переменные env для передачи имен компонентов для маршрутизации

В качестве предупреждения: избегайте маппинга портов, которые не являются необходимыми. Так что не нужно использовать порт 3456:3456 для базы данных postgres. Хотя это не проблема для локальной разработки, если вы используете подобную конфигурацию на рабочем сервере, это может привести к атакам методом грубой силы.

Странный момент: вы могли заметить, что у нас есть и REDIS_URL, и REDIS_HOST env. Это потому, что использование кэша redis по умолчанию требует, чтобы параметр url имел протокол redis:// в начале, но наше приложение также использует redis_store для session_store, который требует только host без протокола. Скорее всего, вы не используете redis_store и можете смело удалить ненужный env.

Уровень 1: добавьте несколько конфигураций качества жизни для разработчиков

Итак, этого конфига мне хватило, чтобы начать работать над проектом и вносить свой вклад, но он не самый удобный из-за нескольких проблем:

Любое изменение в коде требовало отключения инстансов docker-compose, перестройки и повторного включения инфраструктуры, а это уже много.
Я не могу использовать binding.pry для отладки

Поэтому, чтобы сократить количество необходимых перезагрузок и автоматически обновлять код, мы будем использовать тома:

web: build: . volumes: - .:/myapp.

Добавление тома будет зеркально отражать текущий каталог в каталог приложения в образе и автоматически отражать любые изменения, которые мы вносим в код. Хотя это и не поможет с изменениями в конфигурационных файлах, оно будет обрабатывать большинство изменений в реальном времени (предполагается, что мы работаем на типичных конфигурациях dev env)

Чтобы включить доступ к binding.pry, необходимо добавить в веб-сервис следующее

web: build: . volumes: - .:/myapp tty: true # для binding.pry stdin_open: true # для binding.pry.

Но добавление этого не позволит нам просто получить доступ к отладочной консоли из консоли, используемой для запуска docker-compose, нам нужно будет найти id веб-процесса и подключиться к нему:

docker ps docker attach 75cde1ab8133.

Уровень 2: добавление возможности повторного использования и sidekiq

Последнее, чего не хватало в моем случае - это возможности запускать sidekiq. Вначале в этом не было необходимости, но когда разработка продолжилась, нам понадобилось работать над некоторыми асинхронными задачами для обработки длинных процессов импорта данных.

x-my-app: &my_app build: . volumes: - .:/myapp environment: POSTGRES_HOST: db REDIS_URL: redis://redis REDIS_HOST: redis depends_on: - db - redis tty: true # для binding.pry stdin_open: true # для binding.pry services: db: image: postgres volumes: - ./tmp/db:/var/lib/postgresql/data environment: POSTGRES_PASSWORD: пароль web: <<: *my_app команда: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" порты: - "3000:3000" sidekiq: <<: *my_app command: 'sidekiq -L ./log/sidekiq.log -C ./config/sidekiq-dev.yml -P tmp/pids/sidekiq.pid' redis: image: 'redis:5-alpine' Команда: redis-server

Итак, как вы можете видеть, прежде чем приступить к определению сервисов, мы создали блок, который будет содержать все общие настройки между приложением rails и контейнерами процессов sidekiq. Единственные различия - это команда и порты, так как sidekiq не нуждается в открытых портах, и мы не можем иметь два контейнера, пытающихся занять один и тот же порт в любом случае.

И смекалкапосле этого дополнения я бы считал конфигурацию docker готовой для этого проекта. Хотя для первоначальной настройки с созданием/миграцией/посевом базы данных все еще требуется более одной команды, это шаг, требующий дополнительных сценариев поверх docker-compose. Возможно, для другой статьи.
Набор команд

На прощание я хотел бы перечислить команды docker, которые я использовал чаще всего:

  • docker-compose up —build // запустить приложение - docker-compose down // остановить его, если оно работает в фоновом режиме
  • docker-compose ps // проверить статус запущенных образов
  • docker-compose run web bash // выполнить команды
  • docker images // показать список собранных образов
  • docker image prune // удалить неиспользуемые образы, поскольку они могут занимать много места на жестком диске
  • docker ps / docker
  • kill // если docker-compose не справляется с работой

Совет: вы можете создать псевдоним для docker-compose, чтобы не набирать его каждый раз.

Источник