Дата публикации: 09.06.2024 в 17:39

Гайд по деплою web-приложений для новичков. Часть 1

0 комментария

Привет, коллеги! 👋

В web-разработке процесс деплоя играет важную роль. Это ответственный момент (даже торжественный), когда все усилия, потраченные на написание и тестирование кода, воплощаются в “живое” приложение, доступное пользователям. Ведь для этого приложение и делается, чтобы им кто-то пользовался. Каждый разработчик, независимо от уровня и специализации, регулярно сталкивается с задачей деплоя. Это статья в основном рассчитана на новичков, которые учатся разворачивать приложения на сервере и хотят узнать различные варианты, сравнить их и выбрать подходящий.

Деплой- это не просто загрузка кода на сервер (хотя лет 20 назад деплоили приложения по FTP). Прогресс не стоит на месте, приложения стали сложнее и сейчас деплой - это сложный и многоступенчатый процесс, который обычно включает в себя подготовку окружения, установку зависимостей, миграцию базы данных, минимизацию и компиляцию ассетов, проверку работоспособности и, наконец, переключение трафика на новую версию приложения.

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

Особенно важным является настройка деплоя для проектов, которые часто обновляются, и требуют частого развёртывания на сервере.

В этой статье я собрал популярные варианты деплоя приложений, от самых простых, требующих значительной вовлеченности до сервисов по деплою приложений в "один клик" с нулевым временем простоя.

Так как я работаю с Laravel, то и для примера буду деплоить приложение на Laravel. Это будет demo проект-блог, сделанный для демонстрации возможностей админ-панели для проектов на Laravel -MoonShine. Количество кода, пакетов и размеры базы данных можно считать равными обычному проекту-блогу.

Также в рамках этой статьи будем использовать GitHub. Я в работе использую именно его, наверное потому что Laravel использует GitHub (шутка). Всем начинающим разработчикам настоятельно рекомендую использовать git и привыкать к современным инструментам и принципам работы в команде, где без системы контроля версий никак не обойтись.

Вариант деплоя с архивом

Этот вариант уже в архиве истории. Его добавил для того чтобы немного поднять настроение. Брали папочку, подключались по ftp на сервер (я использовал программку FileZilla), загружали архив на сервер и там его распаковывали. Для сайтов-визиток работало неплохо. Всё что сложнее уже могут возникнуть проблемы.

"Классический" деплой на хостинге с использованием GitHub

Считаю что этот "классический" способ должен знать каждый начинающий разработчик, чтобы понимать, что происходит при развертывании приложения на сервере. Используется при этом недорогой хостинг (рублей 200-300/месяц на Timeweb, Beget, Рег.ру и т.д.) без необходимости администрирования. Подойдет для начинающих разработчиков. Дешево и сердито. В этой статье я буду показывать как деплоить на хостинге от beget (можно любой другой).

Требования к хостингу

  • поддерживает версию PHP, которая соответствует вашему проекту (в моём случае 8.3 - настоятельно рекомендую своевременно обновлять свои проекты)

  • есть система управления базами данных MySQL

  • есть возможность подключения по SSH

  • установлена система контроля версий Git

Что еще понадобиться

  • домен связан с хостингом (DNS-серверы хостинга внесены в настройки домена), или есть тестовый домен для проверки работоспособности проекта

  • на рабочем месте установлена система контроля версий Git

  • есть аккаунт на GitHub

Проще говоря - на хостинге уже есть папка с сайтом и в браузере можно вбить домен и сайт будет открываться.

Кроме этого понадобятся знания основ php, git и devops. Ну раз вы занялись деплоем, то наверняка вы разбираетесь в основах.

Начинаем.

Настройка git репозиториев

Переходим на GitHub, создаем новый репозиторий и напишем название - пусть будетCutCodeDeploy- очень красиво. Дополнительно сделаем репозиторий приватным (устанавливаем переключатель вPrivate). Условия приближенные к реальным - обычно, если мы делаем проект на заказ, то заказчику нужна конфиденциальность, для этого и служат приватные репозитории.

Нажимаем кнопку"Create repository". Репозиторий создан и GitHub предлагает нам пошаговую инструкцию - Quick setup. Давайте по ней и работать, чтобы ничего не забыть.

Приступаем.

Инициализируем новый локальный Git репозиторий на компьютере при помощи командыgit init.

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

cd "путь_к_папке_с_вашим_проектом"
git init

Эта команда создала папку.gitвнутри папки с вашим проектом.

Хорошее начало. Осталось совсем немного.

Чтобы Git понимал какие файлы в проекте изменились, нужно добавить их в индекс.

git add -A

Эта команда добавляет содержимое текущего каталога в индекс. И теперь git будет отслеживать изменения в репозитории и какие из файлов мы добавим в следующий коммит.

Коммит в Git - это как сохранение в игре. Когда вы делаете коммит, вы фактически сохраняете текущее состояние вашего проекта. Это позволяет вам в любой момент вернуться к этому состоянию, если что-то пойдет не так в будущем. Важно отметить, что при первом коммите Git добавляет весь проект. В последующих коммитах Git будет добавлять только те файлы, которые были изменены после последнего коммита.

Пора сделать первый commit проекта (с комментарием "исходный проект") в созданный репозиторий:

git commit -m "исходный проект"

и настраиваем ветку главной:

git branch -M master

Представьте, что у вас есть версия проекта (игра, прогресс в которой вы хотите сохранить) на вашем компьютере (это ваша приставка), и вы хотите загрузить его на GitHub, чтобы другие могли им воспользоваться или чтобы вы могли работать над ним с другого компьютера.

Но прежде чем вы сможете загрузить свой проект туда, вы должны "связать" ваш локальный репозиторий на компьютере с удаленным репозиторием на GitHub. Это можно сделать с помощью команды:

git remote add origin https://github.com/"имя_пользователя"/"имя_репозитория".git

Заменитеимя_пользователяиимя_репозиторияна ваше имя пользователя на GitHub и имя вашего репозитория соответственно.

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

git remote add origin https://github.com/CutCodes/CutCodeDeploy.git

Теперь, когда ваш локальный репозиторий связан с удаленным репозиторием на GitHub, вы можете запушить (или отправить) свой проект на GitHub. Это можно сделать с помощью команды git push origin master:

Если вы планируете часто обновлять свой проект, вам, возможно, не захочется каждый раз писать длинную командуgit push origin master. Вместо этого, вы можете сделать команду короче, простоgit push. В конце концов, хороший разработчик - это ленивый разработчик!

Чтобы сделать это, вы можете установить веткуmasterвашего репозитория как ветку по умолчанию для командыgit push. Это можно сделать с помощью следующей команды:

git push -u origin master

Отлично. Проект на GitHub! И теперь, когда вы вводитеgit push, Git автоматически пушит ваши изменения в веткуmasterвашего удаленного репозитория на GitHub. Это делает процесс обновления вашего проекта на GitHub намного быстрее и проще!

Клонируем проект на хостинг из GitHub

Следующая задача - необходимо загрузить проект с GitHub на сервер. Так как мы создали приватный репозиторий на GitHub, нам нужно предоставить нашему серверу доступ к этому репозиторию.

Чтобы это сделать, мы должны установить безопасное соединение между нашим сервером и репозиторием на GitHub.

Для начала, переходим на нашем сервере в консоль. Затем мы создаем новую пару ключей SSH - это приватный и публичный ключи. Эти ключи нужны для установки безопасного соединения.

SSH-ключи создаются командойssh-keygen. Ключи обычно хранятся на сервере в каталоге~/home/"имя_пользователя"/.ssh/"имя_файла".

Когда мы запускаемssh-keygen, мы указываем имя файла, в котором будут сохранены ключи. Также вы можете изменить место хранения ключей и добавить пароль для дополнительной защиты.

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

  • Приватный ключ:~/home/"имя_пользователя"/.ssh/"имя_файла"

  • Публичный ключ:~/home/"имя_пользователя"/.ssh/"имя_файла".pub

Теперь нам нужно добавить публичный ключ на GitHub. Копируем путь к публичному ключу, и при помощью командыcat смотрим его содержимое:

cat ~/home/"имя_пользователя"/.ssh/"имя_файла".pub

Копируем содержимое публичного ключа и переходим в настройки нашего репозитория на GitHub (это раздел "Settings"). Затем мы выбираем раздел "Deploy Keys".

В этом разделе мы добавляем новый ключ деплоя. Мы даем ему название (например, "CutCodeDeploy.beget.tech") и вставляем наш скопированный ключ в соответствующее поле.

После этого мы подтверждаем добавление ключа, нажав на кнопку "Add key".

Важное примечание.

На GitHub еcть опция в виде чекбокса, которая позволяет разрешить запись в репозиторий. Если этот чекбокс не выбран, то по настроенному SSH-соединению можно будет только считывать содержимое репозитория, но не вносить в него изменения.

Обычно для задач деплоя (развертывания проекта) дают доступ только на чтение, так как обычно нам просто нужно забирать обновления из репозитория, а не вносить в него изменения.

Это важно помнить при настройке SSH-соединения с GitHub.

Теперь, когда ключ от сервера для развертывания приватного репозитория добавлен, мы можем настроить взаимодействие между репозиториями на GitHub и сервером.

На GitHub, в нашем репозитории, мы выбираем раздел "Code", затем переходим на вкладку "ssh" и копируем адрес репозитория.

Заходим на сервер, переходим в директорию проекта и в консоли выполняем необходимую команду.

git clone git@"скопированный_адрес_репозитория"

Командаgit cloneвыполняет несколько действий: она инициализирует репозиторий Git в текущей директории, добавляет удаленный репозиторий (известный как"origin") с GitHub, и затем клонирует содержимое этого репозитория в текущую директорию.

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

Настроим git pull

Обновления с репозитория на GitHub можно забрать с помощью командыgit pull origin master. Но мы же разработчики - мы любим эффективность! Использование такой длинной команды каждый раз - это как идти пешком, когда можно проехать на велосипеде.

Поэтому давайте установим веткуmasterв качествеupstream-ветки.

git branch --set-upstream-to=origin/master

Теперь, когда вы хотите забрать обновления, вам просто нужно написатьgit pull, и Git автоматически заберет обновления из веткиmasterрепозиторияorigin, как почтальон, который знает, где ваш почтовый ящик.

Настройка символических ссылок

Точка входа в веб-приложении - это файл, который обрабатывает все запросы к вашему веб-сайту и перенаправляет их в ваше приложение. Обычно это файлindex.phpилиindex.html, который находится в корневом каталоге веб-приложения.

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

Мы используем Laravel. В Laravel точка входа обычно находится в каталогеpublic. Это сделано для обеспечения безопасности, так как только файлы в каталогеpublicдоступны для прямого доступа, а все остальное - под замком. Круто придумано.

Итак, точка входа в приложение Laravel - это файлpublic/index.php, и нам нужно, чтобы все запросы по умолчанию направлялись наpublic/index.php. Простое решение этой задачи - создать символическую ссылку. Это как создать ярлык на рабочем столе, который ведет к нужной программе.

Если в корне проекта уже есть файлindex.phpилиindex.html, то сначала удалим его. А теперь давайте создадим символическую ссылку. Перейдем в корневой каталог вашего проекта Laravel и выполним нужную команду

ln -s public public_html

Это означает, что теперь у вас есть новый путьpublic_html, который ведет прямо в ваш каталогpublic.

Обновляем зависимости

Composer - это мощный инструмент для управления зависимостями в PHP. Он позволяет вам объявлять библиотеки, которые ваш проект использует, и он управляет (устанавливает/обновляет) их за вас. Это как ваш личный помощник, который следит за тем, чтобы все ваши библиотеки были в порядке.

Установка зависимостей Composer при деплое - это важный шаг, который гарантирует, что все необходимые библиотеки и пакеты, необходимые для работы вашего приложения, установлены и настроены правильно на сервере перед запуском вашего приложения. Это как проверка перед стартом, чтобы убедиться, что все готово к запуску.

Composer будет устанавливать все зависимости, указанные в файлеcomposer.jsonвашего проекта. Это как список покупок для вашего приложения, по которому Composer будет следовать.

На некоторых хостингах Composer может быть не установлен по умолчанию. Но обычно у хостинг-провайдеров есть подробные инструкции о том, как установить Composer на их серверах.

Что делать если на хостинге нет Composer?

Если Composer не установлен на сервере, вы всегда можете установить его локально в ваш проект и после этого обновить проект на сервере. Если Composer есть, то пропускаем эту главу -тык.

  1. Сначала мы загружаем установочный файл Composer с помощью команды:

    php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"

  1. Затем мы устанавливаем Composer с помощью команды:


php composer-setup.php

  1. После завершения установки мы можем удалить установочный файл, он нам больше не понадобится:


php -r "unlink('composer-setup.php');"

Теперь в вашем проекте есть файлcomposer.phar, и его можно использовать для управления зависимостями внутри вашего проекта.

Чтобы Composer появился на сервере, обновим проект, выполнивcommitиpushв репозиторий на GitHub:

Затем выполнимpullна сервере. И вуаля, Composer теперь у вас в проекте! Но помните, он доступен только внутри проекта и запускать его нужно командойcomposer.phar.

Продолжаем работу с Composer

На некоторых хостингах, включая хостинг beget, требуется явно указывать версию PHP для Composer. Это связано с тем, что версия PHP в консоли может отличаться от версии, заданной в контрольной панели для сайта. Это как если бы у вас было два разных языка, один для общения с друзьями, и другой - для работы. И Composer должен знать, на каком языке ему говорить.

Вы можете узнать текущую версию PHP для консоли с помощью командыphp -v. Спросим у PHP: "Сколько тебе лет?".

Если на сервере установлено несколько версий PHP, то в команде нужно указывать конкретную версию PHP. В моём случае этоphp8.3.

Командаphp8.3 composer installобновит зависимости в вашем проекте. Однако, эта команда будет работать только в том случае, еслиphp8.3иcomposerдоступны в вашемPATH. Это означает, что оболочка может найти их, когда вы вводите эти команды.

Еслиphp8.3илиcomposerне найдены, вам придется указать полный путь до этих программ. Например, еслиcomposerнаходится в/usr/local/bin/composer, вы должны использовать этот полный путь в команде.

Алиасphp8.3обычно создается при установке этой версии PHP. Это делается для удобства, чтобы можно было легко переключаться между разными версиями PHP.

Выполним:

php8.3 composer install

По этой команде все необходимые нашему приложению пакеты Composer скачает и установит, вот такой он молодец.

Пару слов о composer.lock

В проектах, которые используют Composer, есть важный служебный файл под названиемcomposer.lock. Этот файл выполняет несколько ключевых функций:

Фиксация версий зависимостей: когда вы впервые устанавливаете зависимости с помощью командыcomposer install, Composer смотрит на файлcomposer.jsonвашего проекта, чтобы узнать, какие пакеты ему нужны, и скачивает их. Затем Composer записывает точные версии установленных пакетов вcomposer.lock. Это означает, что если вы или кто-то другой запуститеcomposer installв будущем, Composer будет использовать версии изcomposer.lock, а не искать новые версии. Это гарантирует, что все, кто работает над проектом, используют одни и те же версии пакетов, что уменьшает вероятность проблем совместимости.

Безопасность: файлcomposer.lockтакже содержит хеши каждого пакета. Это позволяет Composer проверить, что пакеты не были изменены или повреждены с момента их установки.

Ускорение установки: файлcomposer.lockсодержит точные версии и источники каждого пакета, поэтому Composer быстрее устанавливает пакеты, не тратя время на их поиск.

Важно помнить, чтоcomposer.lockдолжен быть включен в ваш репозиторий кода, чтобы все, кто работает над проектом, могли использовать одни и те же версии пакетов. Если вы хотите обновить версии пакетов, вы можете использоватьcomposer update, который обновитcomposer.lock.

Создаём базу данных для приложения

Создание базы данных для приложения - это простой процесс. Все, что вам нужно, это найти раздел "Базы данных" в панели управления вашего хостинга.

Затем вы создаете отдельную базу данных для вашего проекта, а также пользователя, который будет иметь доступ к этой базе данных. Обычно имя базы данных совпадает с именем пользователя, это как двойное подтверждение вашей личности.

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

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

Настраиваем .env

Файл.envочень важен для работы проекта на Laravel. Этот файл содержит различные настройки окружения, такие как данные для подключения к базе данных, ключи API и другую конфиденциальную информацию, которая также зависит от окружения..envна продакшене один, у вас локально свой, у коллег по команде другой. Именно поэтому файл.envне присутствует в git-репозитоиях.

Создадим файл.envиз шаблона (.env.example) командой:

 cp .env.example .env

Вот он появился:

Еще один способ просмотреть содержимое текущей директории - это использовать командуls -la. Эта команда отображает все файлы и папки в текущей директории, включая скрытые файлы (те, что начинаются с точки). Выполняем:

ls -la

В консоли вы увидите список всех файлов и папок в текущей директории.

Итак, файл.envсоздан, редактируем его! Первым делом займемсяAPP_KEY. Это ключ безопасности, который очень важен для Laravel, он используется для шифрования данных пользователя, таких как сессии, куки и пароли, а также для защиты от CSRF атак. Без этого ключа ваше приложение Laravel не сможет правильно функционировать.

Надо быть аккуратными при работе сAPP_KEY, ведь если заново сгенерировать ключ на уже рабочем проекте, то все ранее зашифрованные данные (например, пароли пользователей) станут недоступными!

Ключ генерируется командой:

php8.3 artisan key:generate

Теперь в файле.envпоявился новый ключ безопасности в строкеAPP_KEY.

Кроме этого в .env надо установить еще несколько параметров:

  • APP_ENV=productionуказываем что режим работы приложения - продакшен

  • APP_URL="домен приложения"

  • DB_DATABASE="имя БД"

  • DB_USERNAME="имя пользователя БД"

  • DB_PASSWORD="пароль от БД"

Миграции

Миграции в Laravel - это очень удобный способ управления структурой вашей базы данных. Командаphp8.3 artisan migrateзапускает все ваши миграции, что, по сути, “накатывает” изменения на вашу базу данных. А при первом вызове создает структуру базы данных с нуля.

Поскольку вы указалиAPP_ENV=productionв файле.env, Laravel выдает предупреждение перед запуском миграций. Это сделано для того, чтобы предотвратить случайные изменения в вашей продакшен-базе данных. Это двойная проверка перед тем, как вы вносите какие-либо изменения.

Компиляция ассетов и рестарт очередей

Компиляция ассетов и рестарт очередей - это два важных шага, которые легко забыть при развертывании приложения Laravel.

Компиляция ассетов- это процесс, в котором Laravel собирает и оптимизирует ваши CSS и JavaScript файлы. Это делается с помощью инструмента под названием Laravel Mix или Vite, который упрощает работу с ассетами. Вы можете запустить компиляцию ассетов с помощью команды:

npm run prod

Рестарт очередей- это важный шаг, если ваше приложение использует очереди задач Laravel. Когда вы обновляете свое приложение, вам нужно убедиться, что все ваши очереди воркеров перезапускаются. Если в проекте джобы изменились, а вы забудете перезапустить очереди, то изменения не применятся и крутиться в воркерах будут старые джобы.

Рестарт очередей выполняется с помощью команды:

php artisan queue:restart

Проверяем работу

Всё готово для проверки работы. Обновляем страницу и видим наше приложение на Laravel.

Всё настроено. Как теперь обновлять проект?

1. Отправляем изменения в удалённый репозиторий на GitHub.

1.1. Создаём коммит в локальном репозитории:


commit "описание коммита"

1.2. Отправляем изменения в GitHub:


git push

1.3. Проверяем что репозиторий на GitHub обновлён.

2. Теперь заберем изменения из GitHub-репозитория на сервер.

2.1. Переходим в командную строку на сервере. И выполняем:


git pull 

2.2. Устанавливаем зависимости, если вдруг какие-то пакеты новые подключали:


php8.3 composer install 

2.3. Накатываем миграции, собираем ассеты и делаем рестарт очередей:


php8.3 artisan migrate 
npm run prod
php artisan queue:restart

Выводы

Вот так мы практически с нуля настроили деплой проекта на сервер. Примерно это займет около 30 минут. Каждый дальнейший деплой - 3-5 минут. Не очень радостные перспективы для проектов, на которых необходимо часто обновлять код на продакшене. Также не стоит забывать про человеческий фактор, много рутинной работы - можно забыть выполнить какой-то шаг - не обновить зависимости, забыть про миграции, компиляцию ассетов или рестарт очередей. Легко пропустить какую-то команду, а любая оплошность приведет к ошибке при деплое, и нужно будет тратить время на поиск причины.

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

Данил Щуцкий, автор проектаCutCode.

ОбщайсяРазвивайсяУчисьРаботай
ОбщайсяРазвивайсяУчисьРаботай
ОбщайсяРазвивайсяУчисьРаботай
ОбщайсяРазвивайсяУчисьРаботай