Website development
PHP
Yii
28 November 2014

Vagrant для PHP-проекта

Под впечатлением статьи 5 Easy Ways to Get Started with PHP on Vagrant хочу поделиться своим способом использования Vagrant для PHP-проекта.

Чего хотелось достигнуть:
  • На машине разработчика устанавливаются только Vagrant и VirtualBox;
  • Настройки виртуальной машины хранятся в репозитории проекта, позволяя разработчику быстро её разворачивать, а также гибко настраивать под нужды проекта и делиться этими настройками с членами команды;

Этих целей удалось достигнуть с помощью Chef-Solo. Получилась некая заготовка как для создания новых проектов на её основе, так и для интеграции в неё уже существующих проектов: vagrant-php.



Сценарий работы с таким проектом для нового члена команды очень прост:

  1. Необходимо установить Vagrant и VirtualBox, а также несколько плагинов Vagrant:
    $ vagrant plugin install vagrant-librarian-chef-nochef vagrant-omnibus
    
  2. Загрузить проект из репозитория:
    $ git clone repo path
  3. Скопировать 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" и комитится в репозиторий проекта) и предназначен для разворачивания приложения на сервере. Он выполняет следующие действия:
  1. Создание для приложения отдельного системного пользователя (параметры [«php-app»][«user»] и [«php-app»][«group»]);
  2. Создание необходимых каталогов (параметры [«php-app»][«project_dir»] и [«php-app»][«log_dir»]);
  3. Создание отдельных php-fpm pool'ов для приложения (параметр [«php-app»][«php»][«pools»]);
  4. Создание виртуальных хостов Nginx (параметр [«php-app»][«vhosts»]);
  5. Добавление записей в локальный hosts-файл виртуальной машины (параметр [«php-app»][«hosts»]);
  6. Создание баз данных (параметры [«php-app»][«mysql»] и [«php-app»][«pgsql»]);
  7. Загрузка проекта из git-репозитория (при необходимости, см. раздел про расположение проекта);
  8. Установка Composer и всех зависимостей проекта (параметр [«php-app»][«composer»]);
  9. Выполнение произвольных команд (параметр [«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 позволяет развернуть проект практически на любой машине (не обязательно виртуальной) за считанные минуты, при этом не требуя от разработчика никаких дополнительных действий.

Буду рад услышать ваши комментарии.

+6
44.4k 193
Comments 42
Top of the day