Под впечатлением статьи 5 Easy Ways to Get Started with PHP on Vagrant хочу поделиться своим способом использования Vagrant для PHP-проекта.
Чего хотелось достигнуть:
- На машине разработчика устанавливаются только Vagrant и VirtualBox;
- Настройки виртуальной машины хранятся в репозитории проекта, позволяя разработчику быстро её разворачивать, а также гибко настраивать под нужды проекта и делиться этими настройками с членами команды;
Этих целей удалось достигнуть с помощью Chef-Solo. Получилась некая заготовка как для создания новых проектов на её основе, так и для интеграции в неё уже существующих проектов: vagrant-php .
Сценарий работы с таким проектом для нового члена команды очень прост:
- Необходимо установить Vagrant и VirtualBox , а также несколько плагинов Vagrant:
$ vagrant plugin install vagrant-librarian-chef-nochef vagrant-omnibus
- Загрузить проект из репозитория:
$ git clone repo path
- Скопировать Vagrantfile и запустить виртуальную машину:
$ cd path
$ cp .chef/Vagrantfile Vagrantfile
$ vagrant up
Всё, виртуалка развернулась, пакеты установились, приложение работает!
Плагин «vagrant-librarian-chef-nochef» предназначен для загрузки внешних cookbook'ов Chef'а и управления их зависимостями без установки самого Chef'а на локальную машину. Этот плагин позволяет не хранить внешние cookbook'и в своем репозитории, а загружать их при первом включении виртуальной машины.
Плагин «vagrant-omnibus» позволяет указать конкретную версию Chef, которая будет установлена в виртуальную машину (это позволяет использовать практически любой образ с vagrantcloud.com , а также дает возможность зафиксировать версию Chef).
Что внутри?
- Ubuntu Trusty 14.04 (32 bit, current);
- Nginx (последняя версия из Nginx PPA);
- PHP 5.6 (из ondrej PPA), Composer;
- Memcached (из стандартного репозитория Ubuntu);
- MySQL 5.5 (из стандартного репозитория Ubuntu);
- PostgreSQL 9.3 (из PostgreSQL PPA).
Следует отметить, что при желании любой из этих компонентов можно заменить. Сама концепция универсальна.
Как интегрировать данное окружение со своим PHP-проектом?
Если есть существующий PHP-проект, то необходимо загрузить проект из репозитория:
$ git clone repo path
Если же необходимо начать новый проект, то сначала необходимо создать каталог для него:
$ mkdir path
Затем нужно скопировать каталог ".chef" в каталог проекта и внести необходимые настройки в файл ".chef/nodes/10.2.2.10.json" (см. ниже про структуру json-файла) и ".chef/Vagrantfile".
Теперь остается лишь скопировать файл ".chef/Vagrantfile" в корень проекта и запустить виртуальную машину:
$ cd path
$ cp .chef/Vagrantfile Vagrantfile
$ vagrant up
Если создается новый проект, то необходимо войти на виртульную машину через SSH под пользователем приложения (см. ниже про SSH доступ), установить проект с помощью Composer, а затем загрузить содержимое проекта из виртуальной машины в локальный каталог:
$ composer create-project --prefer-dist yiisoft/yii2-app-basic /home/php-app/www
Также желательно добавить строку "/Vagrantfile" в файл ".gitignore" проекта. Это позволит разработчику вносить локальные изменения в настройки виртуальной машины (например, уменьшать размер оперативной памяти), не отражая эти изменения в VCS.
После этого следует проверить работоспособность проекта в виртуальном окружении и если проект работоспособен, то можно делать commit каталога проекта (в новый или уже существующий репозиторий).
SSH доступ
Зайти на виртуальную машину через SSH можно двумя способами:
- Как администратор:
$ vagrant ssh
- Как пользователь, под которым развернуто приложение:
$ ssh php-app@10.2.2.10 -i '.chef/files/id_rsa'
По умолчанию вход по паролям выключен (параметр [«openssh»][«server»][«password_authentication»]), поэтому для входа под пользователем приложения используются ключи, указанные в параметре [«php-app»][«ssh»][«authorized_keys»]. В этом массиве перечислены полные пути к файлам на виртуальной машине. Так как каталог ".chef" монтируется в каталог "/tmp" виртуальной машины, то пути выглядят так: "/tmp/.chef/files/...". По умолчанию указан публичный ключ «id_rsa.pub», приватный ключ для которого лежит тут же под именем «id_rsa».
Структура каталога ".chef"
- files/ — каталог для хранения файлов, используемых в рецепте «php-app» (эти файлы доступны внутри виртуальной машины по пути "/tmp/.chef/files/");
- nodes/ — каталог для хранения настроек виртуальных машин;
- cookbooks/ — каталог для хранения загруженных внешних cookbook'ов (создается автоматически);
- site-cookbooks/ — каталог для хранения внутренних cookbook'ов самого проекта;
- tmp/ — временный каталог (создается автоматически);
- Cheffile — зависимости для внутренних cookbook'ов (нужны для «librarian-chef»);
- Cheffile.lock — зафиксированные версии cookbook'ов (файл создается автоматически);
- solo.rb — файл настроек для Chef-Solo, запускаемого внутри виртуальной машины;
- Vagrantfile — шаблон файла с настройками Vagrant (этот файл будет использоваться другими членами команды в качестве образца).
Структура json-файла с настройками виртуальной машины
В параметре «run_list» перечислены рецепты, которые будут выполнены при разворачивании машины и подготовке окружения. Все остальные параметры являются настройками соответствующих cookbook'ов.
В каталоге ".chef/nodes" есть несколько готовых примеров для приложений на базе фреймворка Yii2:
- yii2_advanced.json — настройки для разворачивания расширенного шаблона приложения Yii2;
- yii2_basic.json — настройки для разворачивания базового шаблона приложения Yii2.
Само окружение никак не завязано на Yii2, но эти настройки можно использовать в качестве примера.
Cookbook «php-app» является локальным (расположен в ".chef/site-cookbooks" и комитится в репозиторий проекта) и предназначен для разворачивания приложения на сервере. Он выполняет следующие действия:
- Создание для приложения отдельного системного пользователя (параметры [«php-app»][«user»] и [«php-app»][«group»]);
- Создание необходимых каталогов (параметры [«php-app»][«project_dir»] и [«php-app»][«log_dir»]);
- Создание отдельных php-fpm pool'ов для приложения (параметр [«php-app»][«php»][«pools»]);
- Создание виртуальных хостов Nginx (параметр [«php-app»][«vhosts»]);
- Добавление записей в локальный hosts-файл виртуальной машины (параметр [«php-app»][«hosts»]);
- Создание баз данных (параметры [«php-app»][«mysql»] и [«php-app»][«pgsql»]);
- Загрузка проекта из git-репозитория (при необходимости, см. раздел про расположение проекта);
- Установка Composer и всех зависимостей проекта (параметр [«php-app»][«composer»]);
- Выполнение произвольных команд (параметр [«php-app»][«init_commands»]).
Данный сценарий описан в файле ".chef/site-cookbooks/php-app/recipes/default.rb" и снабжен комментариями. В процессе разработки приложения этот сценарий может дополняться новыми действиями.
Если в вашем PHP-проекте используется Composer, то в json-файле необходимо заполнить параметр [«php-app»][«composer»][«github_auth_token»], иначе зависимости проекта не будут установлены из-за ограничений Github API. Сгенерировать данный токен можно в настройках аккаунта Github .
Полный список возможных настроек cookbook'а «php-app» можно увидеть в файле ".chef/site-cookbooks/php-app/attributes/default.rb".
Настройка каталога проекта
Расположение каталога проекта в виртуальной машине регулируется параметром [«php-app»][«project_dir»]. Обычно вместе с этим параметром необходимо изменить и параметр [«php-app»][«vhosts»][«variables»][«root»], чтобы виртуальный хост указывал на правильный каталог.
Варианты расположения каталога проекта:
- Проект расположен в общем каталоге (в каталоге "/vagrant" виртуальной машины, равному локальному каталогу проекта);
- Проект расположен вне общего каталога (например, в "/home/php-app/www").
Если проект расположен в общем каталоге, то виртуальная машина работает с теми же файлами, что и разработчик.
Недостатки этого варианта:
- В общем каталоге для всех файлов используется одинаковый режим доступа на стороне виртуальной машины (по умолчанию «777»);
- В общем каталоге не учитывается регистр имен файлов (если на локальной машине используется Windows);
- Для создания символических ссылок в общем каталоге требуется запуск виртуальных машин с правами администратора локальной машины (если на локальной машине используется Windows);
- Если разработчик использует Linux на локальной машине, то дисковые операции с общим каталогом будут крайне медленными (эту проблему можно решить, настроив доступ к общему каталогу через NFS в Vagrantfile).
Расположение проекта вне общего каталога (например, в "/home/user/www") позволяет приблизится к условиям реального сервера, но тоже имеет некоторые недостатки:
- Разработчику необходимо позаботиться о синхронизации файлов между локальной и виртуальной машиной (переключение между ветками проекта также придется делать дважды — в локальном каталоге проекта и внутри виртуальной машины);
- Локальные git-комиты не будут доступны в виртуальной машине.
Если проект будет расположен вне общего каталога, то в json-файле необходимо заполнить параметр [«php-app»][«git»][«repository»] для загрузки проекта при подготовке виртуальной машины. Для доступа к репозиторию будет использоваться приватный ключ, указанный в параметре [«php-app»][«ssh»][«deployment_key»].
В IDE PhpStorm/IDEA есть возможность настроить deployment-сервер. В этом случае изменения локальных файлов проекта будут автоматически выгружаться в виртуальную машину.
Для этого необходимо добавить deployment-сервер (с помощью кнопки «Add» в меню «File — Settings — Deployment») со следующими настройками (некоторые настройки зависят от настроек в json-файле):
- Type: SFTP
- SFTP host: 10.2.2.10
- Port: 22
- Root path: /home/php-app/www
- User name: php-app
- Auth type: Key pair (OpenSSH)
- Private key file: каталог_проекта/.chef/files/id_rsa
- Passphrase:
- Web server root URL: demo.local
- Deployment path on server: /
- Web path on server: /
Затем нужно назначить добавленный сервер сервером по умолчанию (с помощью кнопки «Use as Default» в меню «File — Settings — Deployment») и установить значение параметра «Upload changed files automatically to the default server» равным «Always» или «On explicit save action» (в окне «File — Settings — Deployment — Options»).
Настройка MySQL-сервера
Для настройки MySQL-сервера используется внешний cookbook «mysql», поэтому для изменения стандартных настроек необходимо использовать ключ «mysql» в json-файле. По умолчанию MySQL-сервер доступен для внешних подключений по стандартному порту.
В параметре [«php-app»][«mysql»][«root_connection»] необходимо указать параметры доступа для администратора баз данных. Пароль администратора устанавливается в параметре [«mysql»][«server_root_password»].
Список создаваемых баз необходимо указать в ключе [«php-app»][«mysql»][«databases»]:
{
...
"php-app": [
...
"mysql": {
"root_connection": {
"host": "127.0.0.1",
"username": "root",
"password": ""
},
"databases": [
{
"name": "yii2advanced",
"username": "root",
"password": "",
"encoding": "utf8",
"collation": "utf8_general_ci"
},
{
"name": "yii2_advanced_tests",
"username": "root",
"password": "",
"encoding": "utf8",
"collation": "utf8_general_ci"
}
]
}
...
],
...
}
Настройка PosgtreSQL-сервера
Для настройки PosgtreSQL-сервера используется внешний cookbook «postgresql», поэтому для изменения стандартных настроек необходимо использовать ключ «postgresql» в json-файле. По умолчанию PostgreSQL-сервер доступен для внешних подключений по стандартному порту.
В параметре [«php-app»][«pgsql»][«root_connection»] необходимо указать параметры доступа для администратора баз данных. Пароль администратора устанавливается в параметре [«postgresql»][«password»][«postgres»]. Этот пароль не должен быть пустым.
Список создаваемых баз необходимо указать в ключе [«php-app»][«pgsql»][«databases»]:
{
...
"php-app": [
...
"pgsql": {
"root_connection": {
"host": "127.0.0.1",
"username": "postgres",
"password": "password"
},
"databases": [
{
"name": "yii2advanced",
"username": "yii2advanced",
"password": "",
"encoding": "UTF8",
"collation": "en_US.UTF-8"
},
{
"name": "yii2_advanced_tests",
"username": "yii2advanced",
"password": "",
"encoding": "UTF8",
"collation": "en_US.UTF-8"
}
]
}
...
],
...
}
Настройка отладки в PhpStorm/IDEA
Чтобы иметь возможность отлаживать приложение, выполняемое внутри виртуальной машины, необходимо добавить PHP-сервер (с помощью кнопки «Add» в меню «File — Settings — PHP — Servers») со следующими настройками:
- Name: demo.local
- Host: demo.local
- Port: 80
- Debugger: Xdebug
- Use path mappings: Включено (каталог проекта должен соответствовать каталогу [«php-app»][«project_dir»])
Затем нужно создать configuration c типом «PHP Web application» (через пункт меню «Run — Edit configurations»), указав созданный PHP-сервер.
Заключение
Полученное окружение получилось достаточно гибким, все настроки ПО полностью прозрачны и настраиваемы. Использование Chef-Solo позволяет развернуть проект практически на любой машине (не обязательно виртуальной) за считанные минуты, при этом не требуя от разработчика никаких дополнительных действий.