21 сентября 2017

Автоматический Deploy проекта на Laravel (+ Nginx + GitHub)

Есть десятки, а то и сотни способов развертывания проектов на сервере в production или в test, однако, мне никакой из популярных не подошел. Не смотря на то, что у GitHub и Amazon есть возможность осуществлять deploy в автоматическим режиме, такой вариант мне тоже не подошел, т.к. для нищебродов такой вариант получается не слишком экономным.

Использовать для deploy php-скрипт тоже оказалось не правильным (ИМХО) и как результат поисков различных вариантов, мне больше всего приглянулся вариант с возможность отправлять webhook на определнный адрес, по которому будет отвечать сам Nginx обрабатывая полученный запрос посредством Lua-скрипта.

Для ленивых я вынес в гит модуль который мы будем использовать в нашей практике.

Предварительная настройка среды

  1. Для правильной работы нам необходимо чтобы Nginx поддерживал работу lua скриптов внутри своих конфигов, для этого необходимо установить пакет nginx-extras и LuaJIT:
apt-get install nginx-extras luajit
  1. Теперь надо установить пакетный менеджер LuaRocks, делается это таким же образом:
apt-get install luarocks
  1. После этого необходимо установить зависимые пакеты:
luarocks install JSON4Lua
luarocks install luacrypto
  1. Теперь создадим директорию в которую будет складировать скрипты для скачивания изменений с гита:
mkdir /etc/nginx/lua
cd /etc/nginx/lua

Написание конфига и настройка Nginx

  1. Теперь клонируем репозиторий (подразумевается что у вас уже установлен Git)
git clone https://github.com/ZeusLimited/lua-nginx-deploy.git
  1. Создадим файл для развертывания проекты для определенного домена, например: domain.com.lua:
package.path = '/etc/nginx/lua/lua-nginx-deploy/?.lua;' .. package.path

_G.secret = '<MY SUPER SECRET>'
_G.event = 'push'
_G.branch = 'refs/heads/master'
_G.command = 'cd ~www-data/domain.com && git pull'

local deploy = require('deploy')

ngx.header.content_type = "text/plain; charset=utf-8"

if deploy.validate_hook() then
  deploy.run()
end

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

  1. Теперь добавим в конфиг нужного домена следующую директиву:
server {
  # ...
  
  location /deploy {
    client_body_buffer_size 3M;
    client_max_body_size 3M;
    
    content_by_lua_file /etc/nginx/lua/domain.com.lua;
  }
}
  1. Перезапустите nginx:
nginx -s reload

Настройки операции развертывания

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

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

  1. Но для начала нам нужно клонировать наш репозиторий локально на сервер:
cd ~www-data/
git clone [email protected]:[github-account]/[repo-name].git
  1. Выполним все комманды для развертывания проекта (пример для Laravel):
cd ~www-data/[repo-name]
composer install --optimize-autoloader
php artisan config:cache
php artisan route:cache
  1. (Опционально) Если надо сразу накатить миграции, то выполним еще и эту комманду:
php artisan migrate

Конфигурируем Git для выполнения комманд после получения изменений

  1. Зайдем по адресу нашего проекта и убедимся в работоспособности. Nginx должен быть уже настроен, .env файл создан и все при необходимости создана БД с нужными пользователями.

  2. Теперь создадим скрипт развертывания для git:

    touch ~www-data/[repo-name]/.git/hooks/post-merge
    

И скопируем в этот файл все ранее выполненные комманды для разваертывания:

#!/bin/bash
export COMPOSER_HOME="/var/www"
composer install --optimize-autoloader
php artisan config:cache
php artisan route:cache
php artisan migrate
  1. Не забудем проставить права запуска данного скрипта:
chmod +x ~www-data/[repo-name]/.git/hooks/post-merge

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

На стороне GitHub нужно добавить новый Webhook со следующими параметрами:

  • Payload URL: https://[наш публичный адерс сайта]/deploy
  • Content type: application/json
  • Secret: <MY SUPER SECRET>

Сделать вебхук активным и оставить срабатывание только на push.


tl;dr

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