Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Деплой на PaaS Продакшен и Деплой

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

Heroku — самый популярный из таких сервисов. Он поддерживает большое число языков и фреймворков из коробки. Что это значит? Во время деплоя Хероку самостоятельно определяет стек проекта и выполняет все необходимые шаги для обновления. Идеально для обучения хорошим практикам.

В этом курсе мы будем деплоить приложение devops-example-app созданное специально для курса. Оно написано на JavaScript из-за простоты и распространенности. Все подходы, которые мы изучим на нем, работают практически без изменения и для других стеков.

С нуля до работающего приложения

  1. Зарегистрируйтесь на Хероку (может потребоваться VPN)

  2. Создайте новое приложение (application). Хероку проверяет что имя нового приложение уникально среди всех приложений. Это нужно для генерации домена, по которому будет доступно приложение. Имя можно не указывать, тогда Хероку придумает его за вас.

Новое приложение в Heroku

  1. Скачайте и установите утилиту Heroku CLI, которая нужна для связи репозитория с Хероку. Выполните логин

    heroku login
    
    heroku: Press any key to open up the browser to login or q to exit:
    Opening browser to https://cli-auth.heroku.com/auth/cli/browser/<some code>
    Logging in... done
    
  2. Клонируйте репозиторий devops-example-app и свяжите его с созданным в Хероку приложением devops-application.

    heroku git:remote -a devops-application
    
    set git remote heroku to https://git.heroku.com/devops-application.git
    
  3. Теперь деплой. Для этого достаточно отправить код в ветку main удаленного репозитория heroku:

    git push heroku main
    
    Enumerating objects: 175, done.
    Counting objects: 100% (175/175), done.
    Delta compression using up to 8 threads
    Compressing objects: 100% (76/76), done.
    Writing objects: 100% (175/175), 346.73 KiB | 86.68 MiB/s, done.
    Total 175 (delta 78), reused 175 (delta 78), pack-reused 0
    remote: Compressing source files... done.
    remote: Building source:
    remote:
    remote: -----> Building on the Heroku-20 stack
    remote: -----> Determining which buildpack to use for this app
    remote: -----> Node.js app detected
    remote:
    remote: -----> Creating runtime environment
    remote:
    remote:        NPM_CONFIG_LOGLEVEL=error
    remote:        NODE_VERBOSE=false
    remote:        NODE_ENV=production
    remote:        NODE_MODULES_CACHE=true
    remote:
    remote: -----> Installing binaries
    remote:        engines.node (package.json):  14.x
    remote:        engines.npm (package.json):   unspecified (use default)
    remote:
    remote:        Resolving node version 14.x...
    remote:        Downloading and installing node 14.19.0...
    remote:        Using default npm version: 6.14.16
    remote:
    remote: -----> Installing dependencies
    remote:        Installing node modules
    remote:        added 803 packages in 6.781s
    remote:
    remote: -----> Build
    remote:
    remote: -----> Caching build
    remote:        - node_modules
    remote:
    remote: -----> Pruning devDependencies
    remote:        removed 658 packages and audited 144 packages in 6.155s
    remote:
    remote:        11 packages are looking for funding
    remote:          run `npm fund` for details
    remote:
    remote:        found 2 moderate severity vulnerabilities
    remote:          run `npm audit fix` to fix them, or `npm audit` for details
    remote:
    remote: -----> Build succeeded!
    remote: -----> Discovering process types
    remote:        Procfile declares types     -> (none)
    remote:        Default types for buildpack -> web
    remote:
    remote: -----> Compressing...
    remote:        Done: 38.7M
    remote: -----> Launching...
    remote:        Released v3
    remote:        https://devops-application.herokuapp.com/ deployed to Heroku
    remote:
    remote: Verifying deploy... done.
    To https://git.heroku.com/devops-application.git
     * [new branch]      main -> main
    

Проверяем. Правда просто?)

Шаги деплоя

Самое интересное происходит на этапе пуша в heroku. Разберем по шагам, что там произошло.

Первым делом Хероку пытается определить стек. Вероятнее всего проверяется наличие файла package.json, который однозначно указывает на Node.js.

remote: -----> Building on the Heroku-20 stack
remote: -----> Determining which buildpack to use for this app
remote: -----> Node.js app detected

Выставляются важные переменные окружения для Node.js. В первую очередь это кеширование node_modules для ускорения последующих деплоев и NODE_ENV, которая отвечает за работу приложения в различных режимах. По умолчанию Хероку считает что это продакшен режим.

remote: -----> Creating runtime environment
remote:
remote:        NPM_CONFIG_LOGLEVEL=error
remote:        NODE_VERBOSE=false
remote:        NODE_ENV=production
remote:        NODE_MODULES_CACHE=true

Выбирается версия Node.js и NPM. Хероку смотрить что указано в package.json и если находит там информацию о версии, то использует ее. Если нет, то подключает какое-то значение по умолчанию.

remote: -----> Installing binaries
remote:        engines.node (package.json):  14.x
remote:        engines.npm (package.json):   unspecified (use default)
remote:
remote:        Resolving node version 14.x...
remote:        Downloading and installing node 14.19.0...
remote:        Using default npm version: 6.14.16

Устанавливаются все зависимости, включая те что нужны только во время разработки.

remote: -----> Installing dependencies
remote:        Installing node modules
remote:        added 803 packages in 6.781s

Теперь самое интересное, выполняется сборка. Сборка в зависимости от стека может означать разное, где-то это компиляция, где-то транспиляция, в случае TypeScript, где-то подготовка файлов для фронтенда.

Хероку не знает как выполняется сборка в конкретном проекте, но знает, что в Node.js есть команда npm build, которую, по соглашениям, используют все проекты, чтобы собирать проект одной командой. В других стеках есть аналогичные команды, там где они имеют смысл.

remote: -----> Build

Кешируются установленные зависимости для ускорения повторных деплоев.

remote: -----> Caching build
remote:        - node_modules

Удаляются dev-зависимости, которые были установлены для сборки проекта.

remote: -----> Pruning devDependencies
remote:        removed 658 packages and audited 144 packages in 6.155s
remote:
remote:        11 packages are looking for funding
remote:          run `npm fund` for details
remote:
remote:        found 2 moderate severity vulnerabilities
remote:          run `npm audit fix` to fix them, or `npm audit` for details
remote: -----> Build succeeded!

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

remote: -----> Discovering process types
remote:        Procfile declares types     -> (none)
remote:        Default types for buildpack -> web
remote:
remote: -----> Compressing...
remote:        Done: 38.7M
remote: -----> Launching...
remote:        Released v3
remote:        https://devops-application.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.

Проверка пул реквестов (Heroku Pipelines)

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

Пайплайны на Heroku

Непрерывная доставка

Хероку позволяет пойти еще дальше и настроить непрерывную доставку (CD). В такой схеме, деплой происходит автоматически по коммиту в определенную ветку.

Возникает вопрос, а что если коммит что-нибудь ломает? Такая вероятность есть, поэтому непрерывная доставка подразумевает определенную инженерную культуру. Речь идет, в первую очередь, о тестах, которыми покрыта большая часть кода. Сами тесты должны запускаться на каждый коммит в сервисе непрерывной интеграции (CI), таком как Github Actions.

Настройка непрерывной доставки делается на вкладке Deploy. Там подключается репозиторий на гитхабе и выставляется флажок wait for CI to pass before deploy. Тогда Heroku будет ждать прохождения всех проверок на CI перед деплоем.

Непрерывная доставка на Heroku

Кроме тестов, для CD важно то как мы работаем с базой данных. Подробнее об этом далее в уроках.


Самостоятельная работа

  1. Зарегистрируйтесь на Heroku

  2. Выполните деплой devops-example-app


Дополнительные материалы

  1. Что такое деплой
  2. Релизы и Роллбеки на Heroku

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Для полного доступа к курсу нужен базовый план

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

Получить доступ
900
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 130 курсов, 2000+ часов теории
  • 900 практических заданий в браузере
  • 360 000 студентов
Даю согласие на обработку персональных данных, соглашаюсь с «Политикой конфиденциальности» и «Условиями оказания услуг»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Даю согласие на обработку персональных данных, соглашаюсь с «Политикой конфиденциальности» и «Условиями оказания услуг»