Привет, коллеги! 👋
В 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 есть, то пропускаем эту главу -тык.
-
Сначала мы загружаем установочный файл Composer с помощью команды:
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
-
Затем мы устанавливаем Composer с помощью команды:
php composer-setup.php
-
После завершения установки мы можем удалить установочный файл, он нам больше не понадобится:
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.