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

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

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

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

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

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

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

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

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

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

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

Считаю что этот "классический" способ должен знать каждый начинающий разработчик, чтобы понимать, что происходит при развертывании приложения на сервере. Используется при этом недорогой shared-хостинг (рублей 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 ~.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

update

При клонировании репозитория с помощью Git, ссылка на исходный репозиторий автоматически устанавливается как origin. Это означает, что Git знает, откуда получать данные при выполнении git pull.

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

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

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

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

update

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

Итак, точка входа в приложение 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.

Комментарии (25)


  1. FanatPHP
    11.06.2024 05:08
    +9

    Статья вызывает смешанные чувства. С одной стороны, написана довольно добротно. Но с другой - затянута она просто чудовищно. Я листал, листал, листал, листал, листал, листал, листал и всё ждал - а где же будет про деплой-то? И долистал:ssh prod, git pull.

    ОК, я понимаю - про ansible, docker или Github Actions будет написано в других частях, наверное. Но увидеть вместо этого букварь по работе с гитом я как-то совсем уж не ожидал. При том что представить себе юзкейс для такой последовательности действий я не могу. Если человек не использовал гит при разработке, для которой он, вообще-то, и нужен, то тащить его для деплоя как-то странно. Залить зип архив через ту же файлзиллу ему будет и проще, и привычнее. Ну то есть либо у него уже есть гит - и тогда половину статьи можно выкинуть, или гита нет - и тогда ту же половину можно выкинуть тоже (и написать гайд по файлзилле).

    Причем и в самом этом букваре снова хромает логика. git push с локали без ключа, разумеется, не сработает. А этот кусок не разжёван. То есть либо текст всё-таки пишется в расчете на человека, который уже пользуется гитом - и тогда половину статьи можно выкинуть, либо всё это разжёвывание в мелкую кашицу всё равно не сработает, поскольку процесс сломается уже в самом начале.

    То же самое касается композера. Ну если человек пишет под Ларавал, то представление о пакетном менеджере он же уже должен иметь. Зачем перегружать статью?

    Или ликбез по символическим ссылкам. Ну ОК, я понимаю, что подводный камень, который стоило обозначить. Но свою целевую аудиторию, для которой делается это разжевывание, вы к этому моменту уже потеряли. Объем новой информации, которую может усвоить человек, довольно ограничен. И примерно к середине статьи он уже перестанет что-либо воспринимать.

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

    В целом у меня претензия, пожалуй, только к несоответствию между названием и содержанием. Это точно не гайд по деплою. Я бы предложил либо выкинуть раздел про гит (и таким образом избавиться от шизофренического "вам понадобится знание основ git, но мы их вам все равно расскажем"), либо переназвать эту часть как "Гайд по деплою web-приложений на Laravel для новичков. Часть 1, подготовка проекта на своем компьютере", добавить в нее руководство по созданию ssh ключей под венду, перелить в неё всю воду про композер и на этом завершить. С тем, чтобы люди, интересующиеся именно деплоем, могли с чистой совестью её пропустить.

    А следующую часть назвать "Гайд по деплою web-приложений на Laravel для новичков. Часть 2, выкатываем на shared hosting" и там уже расписывать костыли для копеечного хостинга, с символическими ссылками и композером в репе. Оставив в ней только генерацию ключей, а за картинками заливки на гитхаб отсылать к предыдущей части.

    Из замеченных косяков

    • Команду cat ~/home/"имя_пользователя"/.ssh/"имя_файла".pub надо конечно заменить на cat ~/.ssh/имя_файла.pub.

    • Устанавливать upstream для клонированного репозитория не нужно, он ставится автоматом. То есть пассаж про программистов, любящих эффективность можно выкинуть.

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

    • Ну и в целом рекомендую проверить весь описанный воркфлоу на чистой системе, причём как удаленной, так и локальной.


    1. Desert-Eagle
      11.06.2024 05:08
      +1

      Комментарий вызывает смешанные чувства. С одной стороны написан добротно, но затянут чудовищно. У людей посты меньшего объема, чем ваш комментарий.


      1. Smirninini
        11.06.2024 05:08
        +1

        Норм коммент) Наименование не соответствует. Статья в целом не про деплой, а про гит, composer, laravel, переменные окружения и пр. Web-приложенния это не только php и laravel. Есть java spring, flask, django, rails, go, js и др. Деплой это не только копирование по ftp, git push и pull и выполнение команд. Есть специальные библиотеки, docker, docker-compose, kubernetes, ci/cd разные.