Hitech logo

Кейсы

Kamal: настройка и лайфхаки, позволяющие увеличить эффективность и не думать о рутинных задачах

TODO:
Иван Солдатов14 сентября 2023 г., 07:53

Сегодня процесс деплоя — это ключевой этап разработки, требующий надёжности и гибкости. С ростом популярности Docker появились инструменты для упрощённой работы с контейнеризацией. Kamal (ранее MRSK) предлагает простое и эффективное решение для развёртывания Rails-приложений в Docker-контейнерах. В отличие от Capistrano, Kamal автоматизирует настройку серверов и управление зависимостями, что позволяет быстро развернуть приложения на «чистых» серверах с минимальной настройкой. Иван Гришков, full-stack разработчик и эксперт в Ruby on Rails, расскажет о том, как Kamal способен значительно повысить скорость разработки без усложнения самого процесса, и как с его помощью настраивать деплой Rails-приложения в Docker, сохраняя контроль и удобство.

Самые интересные технологические и научные новости выходят в нашем телеграм-канале Хайтек+. Подпишитесь, чтобы быть в курсе.

Почему Kamal?

Ранее частым выбором для деплоя Rails-приложений был Capistrano. Он предоставлял удобные инструменты для автоматизации, но со временем начали проявляться его ограничения: каждый новый сервер требовал тщательной подготовки, что превращало поддержку инфраструктуры в постоянную борьбу с конфигурациями Ansible или Chef.

Для контейнеризации стали использовать Docker Swarm или Kubernetes, но эти системы усложняют процесс — Docker Swarm требует понимания согласования состояния, а Kubernetes подходит далеко не всем, хоть и является мощным инструментом сам по себе.

У Kamal же совершенно другой подход, предлагающий простое решение, объединяя преимущества Capistrano и Docker для деплоя контейнеризированных приложений. Kamal исключает ручную настройку серверов и зависимости — достаточно подключить «чистые» серверы с добавленным SSH-ключом, и остальное Kamal сделает за вас. Он установит Docker и развернёт приложение в течение нескольких минут.

Это элегантное решение позволяет разворачивать приложения с помощью Docker без дополнительных усложнений. Kamal использует базовые команды Docker, что делает его понятным даже для тех, кто только начинает осваивать контейнеризацию. Он позволяет сосредоточиться на главном — успешном развёртывании приложения.

Начало работы и особенности Kamal

В этой статье я не буду рассказывать о базовых конфигурациях, доступных в документации. Вместо этого мы погрузимся в особенности и тонкости настройки Kamal.

Конфигурация Builder

В данной конфигурации есть несколько важных моментов:

● Multistage-config — для минимизации веса Docker-образа рекомендуется использовать многоступенчатую сборку, где слой сборки приложения собирается отдельно, и в финальный образ включается только чистый код без лишних артефактов сборки.

● Dockerfile — все Docker-файлы размещены в папке .dockerdev для удобства и безопасности.

● Multiarch — позволяет указать необходимость многоархитектурнойсборки, что особенно полезно при использовании различной архитектуры на локальной машине и в продакшене. Например, при использовании M1 (aarch64) локально и amd64 на сервере. В CI multiarch: false, что делает билд быстрее.

● Args — передача переменных окружения, таких как версия Ruby, напрямую в контейнер. Чтобы не обновлять конфигурацию каждый раз, версия Ruby берется из стандартного файла: RUBY_VERSION: <%= File.read ('.ruby-version').chomp %>.

Настройка серверов

Kamal изначально не был предназначен для развёртывания приложений на одном сервере, однако в данном примере мы воспользуемся лайфхаком, указав общий хост и объединив их в одну сеть.

Для удобства и простоты конфигурации IP сервера хранится в переменной окружения. Это позволяет явно указать один и тот же хост для обоих контейнеров, чтобы они запускались на одном сервере.

● Network — для взаимодействия контейнеров, таких как приложение и база данных, они должны находиться в одной Docker-сети. Kamal отвечает за запуск контейнеров, но не за их взаимодействие, поэтому сеть необходимо создать заранее.

Чтобы создать сеть, можно подключиться к серверу и вручную выполнить команду docker network create sky-db-net, либо воспользоваться хуками Kamalдля автоматизации этого процесса.

Настройка балансировщика: Traefik

И наконец, вишенка на торте — настройка балансировщика с помощью Traefik. Любое веб-приложение нуждается в правильном взаимодействии с внешним миром. Ранее повсеместно использовался Nginx. В то же время Nginx не всегда эффективно работает с Docker-контейнерами «из коробки» и так на смену ему пришёл Traefik — прокси-сервер, который изначально задуман для интеграции с Docker и автоматизации большинства задач.

В базовом варианте Traefik обеспечивает простой роутинг с домена на сервис, однако в моём случае мне нужно было настроить более сложную логику перенаправления. Например, при переезде веб-портала с Tilda на собственную корзину покупок необходимо было сохранить все старые ссылки и настроить перенаправление с одной ссылки на основной домен. Это удалось реализовать с помощью middleware в Traefik, где все запросы с субдомена перенаправляются на основной домен, сохраняя структуру ссылок.

Ну и самое приятное — чтобы выпустить SSL-сертификат, не нужно вручную настраивать Certbot, прописывать конфигурации и настраивать cron для повторного обновления. Достаточно указать в конфигурации, что используем TLS, и выбрать certresolver: letsencrypt. Указываем домены в массиве, для которых будут получаться сертификаты, и Traefik сделает всё за нас.

Также стоит упомянуть несколько ключевых настроек контейнера с Traefik. Мы публикуем порт 443, чтобы обеспечить безопасное соединение, и используем volume для хранения сертификатов, чтобы они не терялись при перезапуске контейнеров. Кроме того, Traefik должен быть в одной сети с остальными сервисами (network: sky-db-net), чтобы он мог корректно направлять запросы.

Обязательно используем volume, чтобы наши сертификаты сохранялись на сервере, а не в контейнере, и не терялись при перезапуске. Настройка publish: 443 указывает, что только безопасное HTTPS-соединение будет доступно извне. Также важно включить Traefik в ту же Docker-сеть, что и остальные сервисы, чтобы он мог направлять запросы на нужные контейнеры.

Заключение

Kamal стал для меня настоящим открытием — он не только избавляет от рутинной настройки серверов, но и дарит гибкость, необходимую для быстрого и надёжного разворачивания приложений. Благодаря Kamal я могу сосредоточиться на разработке и улучшении своего приложения, а не тратить время на управление инфраструктурой. Быстрые развёртывания, легкие откаты и простота настройки — всё это делает Kamal незаменимым инструментом в моём арсенале.

В этой статье я постарался одновременно и базово ввести в работу Kamal (прежде MRSK), и раскрыть отдельные неочевидные лайфхаки, повышающие эффективность работы с ним. Надеюсь, это поможет вам уверенно шагнуть в мир контейнеризированного деплоя Ruby on Rails приложений. В следующем цикле статей я расскажу уже о более продвинутых конфигурациях Kamal, автоматизации бэкапов и интеграции с другими инструментами для создания полноценного CI/CD пайплайна, а детальнее о Ruby on Rails я делюсь здесь. Оставайтесь на связи, впереди ещё много интересного!