Технологии8 阅读

Kamal2: руководство для начинающих по развертыванию на VPS

Сейчас в качестве full-stack фреймворков я использую в основном Next.js 16 и Rails 8. Работая с Rails, я познакомился с официально рекомендованным инструментом развертывания Kamal. Обычно я использую его для развертывания проектов на RN и серверах Alibaba Cloud. Работать с ним очень удобно и просто, и теперь я хочу рассказать вам о концепции Kamal2 и основах его использования.

Эта статья не будет с самого начала углубляться в слишком сложные вещи. Я хочу сначала ясно объяснить самое главное в Kamal2: что это такое, чем оно может нам помочь, как с ним начать работать, и какие операции используются чаще всего. В конце я приведу пример использования с Next.js, чтобы помочь вам применить полученные концепции к конкретному проекту.

Что такое Kamal2

Если описать одной фразой, Kamal2 — это инструмент для **развертывания приложений через SSH + Docker**. Он не предоставляет полноценной платформы, как Heroku, и не является тяжеловесной системой оркестрации, как Kubernetes; скорее, он превращает «развертывание группы контейнеров Docker» в набор повторяемых команд и конфигураций.

Основная идея Kamal довольно прямолинейна:

Это то, что мне нравится в Kamal. Он не вводит много дополнительных абстракций; вы примерно понимаете, что он делает, поэтому при возникновении проблем их легче диагностировать.

Для каких сценариев подходит Kamal2

Я считаю, что Kamal особенно хорошо подходит для следующих ситуаций:

Другими словами, Kamal не заменяет Docker, а помогает сделать развертывание Docker более удобным.

Сначала разберемся с основными понятиями

Прежде чем начать, я рекомендую запомнить несколько ключевых понятий из Kamal.

config/deploy.yml

Это главный конфигурационный файл Kamal, из которого считываются настройки развертывания. Вы можете рассматривать его как «инструкцию по развертыванию»: здесь указываются имя сервиса, имя образа, список серверов, реестр образов, переменные окружения, builder, proxy и т.д.

.kamal/secrets

Это местоположение файла секретов по умолчанию, Kamal считывает отсюда конфиденциальные переменные. Например, пароль от реестра образов или RAILS_MASTER_KEY для Rails, обычно не прописываются напрямую в deploy.yml, а инжектируются через .kamal/secrets.

kamal setup

Это самая важная команда для первого развертывания. В документации четко указано, что она подключается к серверу, устанавливает Docker (если его нет), входит в реестр образов, собирает образ, отправляет его, забирает, запускает kamal-proxy, запускает новый контейнер и после получения 200 OK от GET /up переключает трафик.

kamal deploy

Это наиболее часто используемая команда для последующих релизов. После успешного первого setup дальнейшее развертывание обычно выполняется с помощью kamal deploy.

Как установить Kamal2

Если у вас уже есть среда Ruby, самый простой способ установки:

bash
gem install kamal

Это стандартный способ установки, указанный в официальной документации. Если Ruby нет, можно запустить Kamal в Docker, но в документации явно указано, что этот способ имеет некоторые ограничения, поэтому на начальном этапе я рекомендую установить его через gem.

После установки можно проверить версию:

bash
kamal version

Инициализация проекта

Перейдите в каталог вашего проекта и выполните:

bash
kamal init

Эта команда инициализирует необходимые для Kamal базовые файлы, самые важные из которых — config/deploy.yml и .kamal/secrets.

Если в вашем проекте уже есть Dockerfile, то у вас уже есть необходимое предварительное условие. Процесс развертывания Kamal по умолчанию строит образ на основе стандартного Dockerfile в корне проекта.

Минимальная рабочая конфигурация

Я рекомендую для начала использовать очень маленький config/deploy.yml. Минимальный пример из официальной документации выглядит примерно так:

yaml
service: myapp
image: your-registry-user/myapp

servers:
  - 203.0.113.10

registry:
  username: your-registry-user
  password:
    - KAMAL_REGISTRY_PASSWORD

builder:
  arch: amd64

env:
  secret:
    - AUTH_SECRET

В этой конфигурации сначала стоит понять следующие пункты:

На этом этапе не стремитесь к полноте конфигурации; важнее сначала обеспечить работу самого базового пути.

Настройка secrets

Далее нужно подготовить .kamal/secrets. Например:

bash
KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
AUTH_SECRET=your-auth-secret

Для проектов Rails в примере документации RAILS_MASTER_KEY считывается из config/master.key. Это одна из причин, почему Rails и Kamal так хорошо сочетаются: новые проекты Rails изначально легко подключаются к этому способу развертывания.

Что происходит при первом развертывании

Когда конфигурация и secrets готовы, можно выполнить:

bash
kamal setup

Эта команда делает многое, но вы можете рассматривать её как «полное первое развертывание». Согласно официальной документации, она выполняет как минимум следующие действия:

  1. Подключается к серверу по SSH.

  2. Если на сервере нет Docker, автоматически устанавливает его.

  3. Выполняет вход в реестр образов локально и на сервере.

  4. Собирает образ с помощью Dockerfile из корня проекта.

  5. Отправляет образ в registry.

  6. Заставляет сервер забрать образ.

  7. Убеждается, что kamal-proxy работает на портах 80/443.

  8. Запускает новый контейнер.

  9. Ожидает, пока GET /up не вернёт 200 OK.

  10. Перенаправляет трафик на новый контейнер.

  11. Останавливает старый контейнер и очищает неиспользуемые образы и остановленные контейнеры.

Здесь есть очень важный момент: **по умолчанию проверка работоспособности выполняется через GET /up**. Поэтому в вашем приложении желательно иметь такой легковесный эндпоинт для проверки работоспособности, иначе новый контейнер может запуститься, но Kamal не переключит на него трафик.

Последующие развертывания гораздо проще

После успешного первого setup для последующих обновлений обычно достаточно выполнить:

bash
kamal deploy

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

С точки зрения пользовательского опыта, самое приятное в Kamal: первое развертывание требует немного больше подготовки, но затем всё становится стабильно.

Часто используемые операции

На начальном этапе я считаю наиболее полезными следующие команды:

Инициализация

bash
kamal init

Генерирует базовые файлы развертывания.

Первое развертывание

bash
kamal setup

Запускает сервер, Docker, образ, прокси и приложение в первый раз.

Последующие релизы

bash
kamal deploy

Самая используемая команда в повседневной работе.

Многосредовое развертывание

Если впоследствии вы начнёте различать staging и production, Kamal поддерживает указание destination с помощью -d, например:

bash
kamal deploy -d staging

Официальная документация поясняет, что в этом случае Kamal объединяет config/deploy.staging.yml и базовую конфигурацию.

Эта возможность очень полезна, но если вы только начинаете, можно пока просто знать о её существовании, не спеша использовать.

Почему он хорошо сочетается с Rails

Новые проекты Rails 8 обычно уже имеют свой Dockerfile, а процесс развертывания Kamal как раз строится вокруг Dockerfile. К тому же в экосистеме Rails естественно воспринимать инструменты на Ruby gem, поэтому знакомство с Kamal через Rails — почти логичный шаг.

Лично для меня именно потому, что я сначала увидел этот подход в проекте Rails, я стал серьёзно рассматривать Kamal как долгосрочное решение для развертывания.

Пример использования Next.js для начального уровня

В завершение приведу пример, более близкий к моей повседневной работе: если я хочу развернуть проект Next.js с помощью Kamal, я обычно делаю из него стандартное Docker-приложение, а затем передаю его Kamal для публикации.

Шаг 1: Настроить Next.js на standalone

В документации Next.js указано, что при включении output: 'standalone' результаты сборки будут содержать .next/standalone с минимальным набором файлов, необходимых для запуска, и файлом server.js. Это отлично подходит для развертывания в Docker, поскольку не требует переноса полной среды разработки.

В next.config.js можно написать так:

js
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'standalone',
}

module.exports = nextConfig

Важно отметить: в документации Next.js сказано, что режим output: 'standalone' больше подходит для непосредственного использования сгенерированного server.js, а не для продолжения использования next start.

Шаг 2: Подготовка Dockerfile

Простой Dockerfile для Next.js может выглядеть так:

Dockerfile
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

FROM node:22-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/static ./.next/static
EXPOSE 3000
CMD ["node", "server.js"]

Здесь важна не столько сама техника Docker, сколько подход: **сначала превратите Next.js в стандартный, запускаемый контейнер, а затем передайте развертывание Kamal.**

Шаг 3: Написать конфигурацию Kamal

Например:

yaml
service: my-next-app
image: your-registry-user/my-next-app

servers:
  - 203.0.113.10

registry:
  username: your-registry-user
  password:
    - KAMAL_REGISTRY_PASSWORD

builder:
  arch: amd64

env:
  clear:
    PORT: 3000
    NODE_ENV: production

Логика этой конфигурации проста:

Шаг 4: Добавить эндпоинт проверки работоспособности

Поскольку Kamal по умолчанию проверяет GET /up, я добавляю в Next.js простейший маршрут, например, в App Router:

ts
export async function GET() {
  return Response.json({ ok: true })
}

Поместите его, например, в app/up/route.ts, и тогда /up будет возвращать простой успешный ответ. Этот эндпоинт должен быть максимально лёгким, его цель — сообщить Kamal: контейнер готов принимать трафик.

Шаг 5: Развертывание

Наконец, возвращаемся к стандартному процессу Kamal:

bash
kamal setup

Последующие обновления:

bash
kamal deploy

Если этот процесс стабильно работает в проекте Next.js, вы заметите: Kamal на самом деле не интересует, используете ли вы Rails. Ему действительно важно, **можете ли вы предоставить стандартный образ Docker и веб-сервис с проверяемой работоспособностью**.

Пока на этом закончим

Если вы, как и я, познакомились с Kamal через Rails 8, а затем постепенно перенесли этот подход в проекты Next.js 16, позиционирование Kamal2 легко понять: это не платформа, а инструмент, который делает самостоятельное развертывание Docker более упорядоченным.

На начальном этапе достаточно освоить следующее:

Когда всё это заработает гладко, можно будет более естественно переходить к изучению многосредовых развертываний, accessories, hooks и сложных конфигураций прокси.

Поделиться

Поделиться

Поделиться этой статьей.