Статьи

Простое развертывание приложений PHP с помощью Deployer

Эта статья обновлена ​​до последней версии Deployer от 26 марта 2017 года.


Каждый пытается автоматизировать процесс разработки, тестирования, форматирования кода, системных проверок и т. Д. Это также касается развертывания наших приложений или отправки новой версии на рабочий сервер. Некоторые из нас делают это вручную, загружая код с помощью FTP-клиента, другие предпочитают Phing , а пользователи Laravel предпочитают Envoyer для этого процесса. В этой статье я собираюсь познакомить вас с Deployer — инструментом развертывания для PHP.

Развертывание логотипа

Демо-приложение

Я буду использовать приложение из предыдущей статьи для демонстрации. Приложение будет развернуто в капле DigitalOcean. Чтобы продолжить, вы можете клонировать исходный код демонстрационного приложения из GitHub .

Установка

Deployer упакован в файл PHAR, который мы можем загрузить на наш локальный компьютер. Мы также можем переместить его в каталог bin пользователя, чтобы сделать его глобальным. Проверьте документацию для более подробной информации.

mv deployer.phar /usr/local/bin/dep chmod +x /usr/local/bin/dep 

Определение серверов

После клонирования демонстрационного репозитория нам нужно создать новый файл с именем deploy.php котором мы определим наши шаги развертывания.

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

 // deploy.php server('digitalocean', '104.131.27.106') ->user($_ENV['staging_server_user']) ->password($_ENV['staging_server_password']); 

Мы также можем определить тип этого сервера ( staging , production и т. Д.), Что позволяет нам запускать задачи (подробнее о задачах позже) на определенной стадии сервера.

 // deploy.php use function Deployer\set; use function Deployer\server; set('default_stage', 'staging'); server('digitalocean', '104.131.27.106') ->user($_ENV['staging_server_user']) ->password($_ENV['staging_server_password']) ->stage('staging') ->env('deploy_path', '/var/www'); 

Нам нужно добавить атрибут default_stage при использовании метода stage. В противном случае мы получим You need to specify at least one server or stage. ошибка.

Примечание . Если вы используете PHP 7, вы можете сгруппировать операторы use в одну строку следующим образом ( use function Deployer\{set, server} ). Вы можете прочитать больше о новых возможностях PHP 7 здесь .

SSH аутентификация

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

 // deploy.php use function Deployer\{set, server}; set('default_stage', 'staging'); server('digitalocean', '104.131.27.106') ->identityFile() ->user($_ENV['staging_server_user']) ->password($_ENV['staging_server_password']) ->stage('staging'); 

По умолчанию метод identityFile использует файл идентификации текущего пользователя ~/.ssh/id_rsa . Мы можем изменить это при необходимости.

 // deploy.php // ... ->identityFile('path/to/id_rsa', 'path/to/id_rsa.pub', 'pass phrase') // ... 

Deployer поддерживает несколько типов SSH-соединений и по умолчанию использует нативный, который использует собственные системные команды для аутентификации.

Установите расширение SSH2

Deployer также поддерживает использование расширения PHP SSH2 . После установки расширения и его включения нам потребуется herzult/php-ssh , который предоставляет оболочку OOP для расширения PHP и устанавливает для ssh_type конфигурации ssh_type значение ext-ssh2 .

 // deploy.php set('ssh_type', 'ext-ssh2'); // ... 

Единственная проблема здесь в том, что у Deployer нет пакета php-ssh , поставляемого с архивом PHAR. Нам нужно будет клонировать repository Deployer, потребовать пакет и, наконец, использовать скрипт build для создания нового архива PHAR.

Использование файлов конфигурации

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

 // servers.yml digitalocean: host: 104.131.27.106 user: root identity_file: ~ stage: staging deploy_path: /var/www/ 

Теперь мы можем загрузить файл внутри нашего файла deploy.php .

 serverList('servers.yml'); 

Определение задач

Задачи — это команды, которые можно запустить с помощью команды dep .

 dep deploy:staging 

Аргумент deploy:staging должен быть задачей внутри нашего файла deploy.php . Мы можем загружать файлы, запускать команды на сервере и т. Д.

 // deploy.php use function Deployer\{server, task, run, set, get, add, before, after, upload}; task('deploy:staging', function() { writeln('<info>Deploying...</info>'); $appFiles = [ 'app', 'bootstrap', 'public', 'composer.json', 'composer.lock', 'artisan', '.env', ]; $deployPath = get('deploy_path'); foreach ($appFiles as $file) { upload($file, "{$deployPath}/{$file}"); } cd($deployPath); run("composer update --no-dev --prefer-dist --optimize-autoloader"); run("chown -R www-data:www-data app/storage"); set('writable_dirs', ['app/storage']); writeln('<info>Deployment is done.</info>'); }); 

Сначала файл выглядит ошеломляющим, но здесь нет ничего особенного. Сначала мы печатаем сообщение, используя метод writeln чтобы уведомить пользователя о начале процесса развертывания. Далее мы определяем папки приложений, которые необходимо загрузить.

Метод upload отправит наши локальные файлы приложения на сервер внутри цикла for . Проверьте документацию для списка доступных функций.

Мы cd в каталог сервера и обновляем наши зависимости Composer, используя метод run , который позволяет нам запускать любую команду оболочки на сервере.

Следующий и последний шаг — сделать необходимые каталоги доступными для записи пользователю сервера, в данном случае www-data для Apache. Параметр writable_dirs сообщает Deployer о наших доступных для записи каталогах. Мы можем достичь того же, используя команду shell.

 dep deploy:staging 

Развернуть 1

 task("deploy:staging", function () { // ... })->desc('Deploy application to staging.'); 

Метод desc добавит справочное сообщение к нашей задаче ( команде ).

Наш текущий файл имеет одну большую задачу для обработки всего процесса развертывания. Мы разделим его на небольшие многократно используемые задачи и будем запускать их одну за другой в deploy:staging задача.

 task('deploy:started', function() { writeln('<info>Deploying...</info>'); }); task('deploy:done', function() { writeln('<info>Deployment is done.</info>'); }); 

Вышеуказанные задачи просто уведомить пользователя о состоянии развертывания. Deployer предоставляет методы after и before ( ловушки ) для запуска задач при запуске других задач.

 before('deploy:staging', 'deploy:started'); after('deploy:staging', 'deploy:done'); 
 task('deploy:upload', function() { $appFiles = [ 'app', 'bootstrap', 'public', 'composer.json', 'composer.lock', 'artisan', '.env', ]; $deployPath = get('deploy_path'); foreach ($appFiles as $file) { upload($file, "{$deployPath}/{$file}"); } }); task('deploy:writable_dirs', function() { $deployPath = get('deploy_path'); cd($deployPath); run("chown -R www-data:www-data app/storage"); set('writable_dirs', ['app/storage']); }); task('deploy:composer', function() { $deployPath = get('deploy_path'); cd($deployPath); run("composer update --no-dev --prefer-dist --optimize-autoloader"); }); 

Осталось только запустить все задачи в deploy:staging задача.

 task('deploy:staging', [ 'deploy:upload', 'deploy:writable_dirs', 'deploy:composer', ]); 

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

Нулевое время простоя

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

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

 /current (link pointing to the current release) /releases /realease_1 /realease_2 /realease_3 

Общие задачи развертывания

У Deployer есть список общих задач, используемых большинством приложений PHP, как мы делали ранее. Мы deploy.php наш deploy.php чтобы по возможности использовать эти общие задачи.

 // deploy.php require_once "recipe/common.php"; set('ssh_type', 'ext-ssh2'); set('default_stage', 'staging'); set('deploy_path', '/var/www'); set('copy_dirs', [ 'app/commands', 'app/config', 'app/controllers', 'app/database', 'app/lang', 'app/models', 'app/src', 'app/start', 'app/tests', 'app/views', 'app/filters.php', 'app/routes.php', 'bootstrap', 'public', 'composer.json', 'composer.lock', 'artisan', '.env', ]); set('shared_dirs', [ 'app/storage/cache', 'app/storage/logs', 'app/storage/meta', 'app/storage/sessions', 'app/storage/views', ]); set('writable_dirs', get('shared_dirs')); set('http_user', 'www-data'); 

Сначала мы устанавливаем некоторые переменные, которые мы будем использовать в наших задачах. shared_dirs , shared_dirs и http_user используются общими задачами.

 task('deploy:upload', function() { $files = get('copy_dirs'); $releasePath = get('release_path'); foreach ($files as $file) { upload($file, "{$releasePath}/{$file}"); } }); 

В этом случае мы сохранили задачу deploy:upload , но вы также можете использовать задачу deploy:update_code для извлечения вашего приложения с удаленных хостов Git. Не забудьте установить необходимые атрибуты при его использовании.

 set('repository', 'http://github.com/whyounes/500pxAPI_Test.git'); set('branch', 'master'); 
 // deploy.php task('deploy:staging', [ 'deploy:prepare', 'deploy:release', 'deploy:upload', 'deploy:shared', 'deploy:writable', 'deploy:symlink', 'deploy:vendors', 'current', ])->desc('Deploy application to staging.'); after('deploy:staging', 'success'); 
  • deploy:prepare : проверить соединение, общую папку, папку релизов и т. д.
  • deploy:release : создать каталог выпуска.
  • deploy:upload : наша задача по загрузке файлов.
  • deploy:shared : создавать общие папки, если они не существуют. Использует атрибуты shared_dirs которые мы установили ранее.
  • deploy:writable : установить доступные для записи каталоги.
  • deploy:symlink : создать символическую ссылку от выпуска к current .
  • deploy:vendors : запустить установку Composer.
  • current : Распечатать название текущей версии.
  • success : Распечатать сообщение об успехе.

Развернуть 2

Развернуть каталоги

Рецепты развертывания

Поскольку большинство из нас использует фреймворки для наших проектов, у Deployer есть несколько предварительно сконфигурированных рецептов для хорошо известных фреймворков, таких как Laravel, Symfony, Yii, Zend и т. Д. Более подробная информация приведена в разделе « Рецепты » в документации.

Вывод

У Deployer действительно хороший API, чтобы сделать процесс развертывания простым и настраиваемым. Если вы никогда не использовали инструмент развертывания для автоматизации процесса развертывания, мы настоятельно рекомендуем вам попробовать его!

Если вы уже использовали Deployer, мы хотели бы услышать ваше мнение! Если у вас есть какие-либо вопросы, вы можете опубликовать их ниже!