Как использовать Deployer с Symfony 6?

Автор: webmasta | Опубликовано:
Обновлено:
deployer

Deployer - это средство автоматического развёртывания веб сайтов (и не только) на продакшн сервере. Многие до сих пор еще пользуются динозаврими методами ручной выгрузки по FTP, но это уже прям совсем моветон. Автоматический деплой - это один из важнейших этапов CI/CD разработки.

Плюсы автоматического деплоя:

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

Минусы... пожалуй только один - разобраться и настроить. Но сделав это один раз, потом можно кайфовать.

Дисклеймер: в интернете очень мало информации о настройке Deployer, не берусь утверждать, что этот гайд является бестпрактисом. Если есть замечания - буду рад их увидеть в комментариях.

Подготовка

  • В качестве локальной системы я использую Ubuntu 22.04, поэтому инструкция будет написана для неё. Пользователям винды сочувствую и советую для разработки поставить убунту хотя бы второй системой.
  • Symfony 6-й версии.
  • Веб сервер с Debian 10 (buster) на борту.

Конфиг

В файле .env вашего проекта должна быть установлена прод среда:

APP_ENV=prod

APP_ENV=dev надо указать в .env.local

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

Создаём SSH ключ для доступа к Github

Более подробную инструкцию можно прочитать здесь, ниже основные моменты.

Сделать это нужно, как на локальной машине, так и на сервере! То есть в итоге надо добавить в гитхаб ДВА ключа. Но скорее всего для локальной машины он у Вас уже добавлен.

Запускаем команду:

ssh-keygen -t ed25519 -C "[email protected]"

В качестве почты надо указать ту, что указана в аккаунте Github.

Когда спросит "Enter passphrase" - оставьте пустым (два раза жмякнуть Enter). У меня из-за этого пароля не хотел deployer заходить на гитхаб.

Как ключ сгенерируется, нужно добавить его в authentication agent (ssh agent).

Запускаем агента:

eval "$(ssh-agent -s)"

Добавляем только что сгенерированный ключ:

ssh-add ~/.ssh/id_ed25519

 

Далее переходим в гитхаб > Settings > SSH and GPG keys > зеленая кнопка NEW SSH key и заполняем форму:

  • title - любое понятное название,
  • key - сам ключ, который находится в содержимом файла ~/.ssh/id_ed25519.pub (вставлять надо ВСЁ, вместе с email в конце).

Чтобы проверить, работает ли ключ, вводим в терминале:

ssh -T [email protected]

В ответ должны получить приветствие и свой логин на гитхабе.

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

Устанавливаем SSH ключ для беспарольного входа на сервер

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

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

Локально запускаем команду:

ssh-keygen -t rsa -b 4096 -C "[email protected]"

Почту можно любую указать, роли это не играет.

Затем копируем ключи на удаленный сервер командой:

ssh-copy-id [email protected]
  • user - имя удаленного пользователя,
  • 100.255.10.10 - ip адрес вашего сервера.

Оно спросит пароль один раз и перенесёт ключи на Ваш сервер.

Проверить вход можно командой:

ssh [email protected]

Пароль при входе теперь не должен спрашивать.

Для деплоера надо добавить запись в конец в файле на вашем ПК ~/.ssh/config:

Host 100.255.10.10
    IdentityFile ~/.ssh/id_rsa.pub
    PubkeyAcceptedKeyTypes +ssh-rsa

Этот файл открыт только для чтения, поэтому редактируем с помощью команды:

sudo nano ~/.ssh/config

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

Настройка сервера

Домен надо сконфигурировать таким образом, чтобы он смотрел на папку www/site.com/current/public.

Перед деплоем папка с сайтом должна быть пустой, удалите всё, что там есть.

Папка current станет символьной ссылкой на текущий релиз.

Я не стал запускать Provision от деплоера, который ставит всё сам от root пользователя, потому что сервер у меня уже настроенный и на нём крутятся другие сайты.

Дополнительно понадобилось лишь:

  • установить ACL:
sudo apt-get install acl
  • установить NPM (не знаю куда он делся, вроде был):
sudo apt-get install -y npm
  • обновить Node.js:
npm install -g n

n lts

Так же должны быть установлены:

  1. Стандартный пакет PHP.
  2. Git.

Посмотреть, что ставит Provision, можно покопавшись в его рецепте.

Устанавливаем и настраиваем Deployer

Локально в папке проекта запускаем:

composer require --dev deployer/deployer

Добавляем алиас для команды dep:

sudo nano ~/.bash_aliases

В конец дописываем:

alias dep='vendor/bin/dep'

И выполняем команду:

source ~/.bash_aliases

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

Если не создать алиас, то вместо короткой команды dep придется использовать vendor/bin/dep.

 

В папке проекта инициализируем его:

dep init

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

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

Открываем конфиг и дописываем секцию (или меняем):

hosts:
  91.200.100.230:
    remote_user: 'user'
    deploy_path: '~/www/site.com/'

deploy_path - относительный юзера путь до сайта на сервере.

Запускаем деплой

Bроде бы можно запустить:

dep deploy

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

Сайт в итоге загрузится на сервер... но мы получим 500-ю ошибку при попытке открыть его ))))

Почему?

Потому что не добавлены таски установки npm зависимостей, билда и миграций.

Вот на этом месте я и застрял немного.

В секции tasks файла deploy.yaml можно указать список заданий, но они не будут запускаться автоматически. Их надо запускать отдельной командой, как оказалось.

Но как быть, если хочется деплоить сайт одной командой? Надо прописать вызов всех необходимых тасков в одном. Получается каскад - один таск будет вызывать остальные.

Новый таск я назвал 'build' - как его назвать, дело исключительно Ваше. Хоть набором рандомных символов, главное включить его в основное задание.

Основной таск я переименовал в deploy-prod (назвать его тоже можно как угодно), который в свою очередь вызывает таск build, в котором я прописал ахалай-махалай связанный с npm:

tasks:
  build:
    - cd: '{{release_path}}'
    - run: 'php bin/console doctrine:migrations:migrate --no-interaction'
    - run: 'npm install && npm audit fix && npm run build'
    - run: uptime

  deploy-prod:
    - deploy:info
    - deploy:setup
    - deploy:lock
    - deploy:release
    - deploy:update_code
    - deploy:shared
    - deploy:writable
    - deploy:vendors
    - build
    - deploy:cache:clear
    - deploy:symlink
    - deploy:unlock
    - deploy:cleanup
    - deploy:success

Таким образом можно создать неограниченное количество тасков. Можно добавить, например, запуск тестов или еще что-то. Главное добавить их в основной таск, либо вызывать отдельно - тут уж зависит от целей.

Теперь полный цикл деплоя (выгрузку, установку зависимостей, установку и сборку node модулей, переключение версии, создание симлинка, очистку кэша и тд...) можно запустить короткой командой:

dep deploy-prod

По поводу названия тасков:

  • названия deploy-prod и build я придумал сам,
  • можно указать любое название, например go или deploy-me или run, роли вообще не играет,
  • главное, чтобы была правильная цепочка и последовательность вызова самих тасков, а как они называются - по барабану.

Каждый таск может содержать в себе любое количество заданий. Есть уже предустановленные задания - рецепты (recipe), которые можно найти в папке vendor/deployer/deployer/recipe/.

Для симфони основной рецепт лежит в файле vendor/deployer/deployer/recipe/symfony.php - его я импортировал в самом начале yaml конфига.

 

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

Полное содержание конфига

Думаю такая информация не будет лишней. Ниже полный YAML конфиг:

import:
  - recipe/symfony.php

config:
  repository: '[email protected]:user/project.git'

hosts:
  100.200.100.200:
    remote_user: 'user'
    deploy_path: '~/www/site.com/'

tasks:
  build:
    - cd: '{{release_path}}'
    - run: 'php bin/console doctrine:migrations:migrate --no-interaction'
    - run: 'npm install && npm audit fix && npm run build'
    - run: uptime

  deploy-prod:
    - deploy:info
    - deploy:setup
    - deploy:lock
    - deploy:release
    - deploy:update_code
    - deploy:shared
    - deploy:writable
    - deploy:vendors
    - build
    - deploy:cache:clear
    - deploy:symlink
    - deploy:unlock
    - deploy:cleanup
    - deploy:success

after:
  deploy:failed: deploy:unlock

Ошибки

fatal: Could not read from remote repository
Please make sure you have the correct access rights and the repository exists.

Решение: надо добавить SSH ключ, созданный на сервере, от имени юзера, на который происходит деплой, в Github. Либо ключ добавлен, но с ошибками.

Полезные ссылки

Добавить комментарий

Ограниченный HTML

  • Допустимые HTML-теги: <a href> <b> <i>
  • Строки и абзацы переносятся автоматически.
  • Адреса веб-страниц и email-адреса преобразовываются в ссылки автоматически.