Налаштування оточення для PHP розробників

У даній статті ми розглянемо налаштування оточення для PHP розробників з використанням Vagrant, Docker, Xdebug, PHPUnit і інтеграцію з IDE PHPStorm.

+

Вимоги
  • Оточення має розгортатися на Windows, MacOS, Linux
  • Установка повинна бути максимально простою
  • Швидка робота з файловою системою
  • Інтеграція з IDE PHPStorm
  • Кілька версії PHP інтерпретаторів (5.6, 7.0)

Підготовка
Ми не будемо загострювати свою увагу на встановленні необхідних інструментів під певні ОС, інструкції по установці є на офіційних сайтах, посилання додаються.

Що входить в збірку?
  • Nginx
  • MySQL 5 (Percona)
  • MongoDB 3
  • Redis 3
  • PHP 5.6, 7.0 CLI + FPM
PHP extensions

5.6
  • cli
  • fpm

  • bcmath
  • gd
  • gmp
  • intl
  • mbstring
  • mcrypt
  • pdo
  • mysqlnd
  • crypto
  • geoip
  • imagick
  • jsonc
  • memcache
  • memcached
  • mongodb
  • ssh2
  • xdebug
  • soap
  • xml
  • opcache
  • redis
7.0
  • cli
  • fpm

  • bcmath
  • gd
  • gmp
  • intl
  • mbstring
  • mcrypt
  • pdo
  • mysqlnd
  • crypto
  • geoip
  • imagick
  • memcache
  • memcached
  • mongodb
  • ssh2
  • xdebug
  • soap
  • xml
  • opcache
  • redis

Налаштування та конфігурування
Увага! Всі описані налаштування і файли викладені на GitHub. Якщо у вас виникають питання по використанню Vagrant або Docker зверніться до офіційної документації.

Розгортання оточення трохи відрізняється на різних ОС:

  • MacOS все пройде, як годиться без додаткових дій.
  • Windows вам необхідно запустити допоміжний скрипт hosts-set.cmd для встановлення прав поточному користувачу на запис для hosts файлу до запуску vagrant up, також якщо у вас ім'я поточного користувача містить будь-які символи non-ASCII, то вам доведеться змінити шлях до вашої робочої директорії vagrant.d використовуючи змінну оточення VAGRANT_HOME.
  • Linux розсуд, можна поставити Vagrant з NFS сервером або просто використовувати docker-compose інструкції.
hosts-set.cmd
@if (1==1) @if(1==0) @ELSE
@echo off&SETLOCAL ENABLEEXTENSIONS
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"||(
cscript //E:JScript //nologo "%~f0"
@goto :EOF
)
CACLS %SystemRoot%\system32\drivers\etc\hosts /E /G %USERNAME%:W
@goto :EOF
@end @ELSE
ShA=new ActiveXObject("Shell.Application")
ShA.ShellExecute("cmd.exe","/c \""+WScript.ScriptFullName+"\"","","runas",5);
WScript.Sleep(500)
@end

Гостьова ОС буде працювати на Ubuntu 14.04 (Вірного), статичний IP адресі 10.0.0.2 і як share-папки будемо використовувати монтування через NFS.

Для зручності створіть папку під назвою dockrant (Docker + Vagrant = Dockrant), далі в статті ми будемо відштовхуватися від цієї папки.

Визначимося зі структурою папок:

./dockrant — наша коренева папка
./dockrant/ssh — SSH ключики для гостьової ОС (в даному туториале використовуємо стандартні ключі vagrant)
./dockrant/share — share-папка між хост і гостьової ОС
./dockrant/share/tools — папка з нашими інструментами і bash скриптами
./dockrant/vagrant/build — виконувані bash скрипти при піднятті гостьової ОС
Тепер нам необхідно по структурі папок описаних вище покласти все необхідні наші скрипти та інструкції, підемо за списком.

./dockrant/ssh — покладемо два файлу id_rsa (приватний ключ) і id_rsa.pub (публічний ключ)

id_rsa
----- BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA6NF8iallvQVp22WDktkyrtvp9eww6a8yvr+kz4TjGYe7gHzI
w+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzuftdoklv6iedplqop
kcmF0aYet2PkEDo3MlTBckFXPITAMzF8djsifo9d8hfdov0iadx4o7ptixwkn5y2
hMNG0zQPyUecp4pzC6kivAIhyfHilFR61rgl+GPXQ2MWZWFYbAGjyiYJnAmCP3NO
Td0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcW
yLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9whqibiwkcaqea4iqwpjxtzza68mkd
ELs4jJsdyky+ewdZeNds5tjcnHU5zUYE25K+ffJED9qUWICcLZDc81TGWjHyAqD1
Bw7XpgUwFgeUJwUlzQurAv+/ySnxiwuaGJfhFM1CaQHzfXphgVml+fZUvnJUTvzf
TK2Lg6EdbUE9TarUlBf/xPfuEhMSlIE5keb/Zz3/LUlRg8yDqz5w+QWVJ4utnKnK
iqwZN0mwpwU7YSyJhlT4YV1F3n4YjLswm5wjs2oqm0jssqu/BT0tyEXNDYBLEF4A
sClaWuSJ2kjq7KhrrYXzagqhnSei9ODYfshju8uwvec3ihb5zxlzo6vdnq1j9xsf
4m+2ywKBgQD6qFxx/Rv9CNN96l/4rb14HKirC2o/orApiHmHDsURs5rUKDx0f9iP
cXN7S1uePXuJRK/5hsubaOCx3Owd2u9gD6Oq0CsMkE4CUSijcyrmantx54cgh7rk
EjFZxK8xAv1ldELEyxrFqkbE4BKd8QOt414qjvtgyak+OLD3M2QdCQKBgQDtx8pN
CAxR7yhHbIWT1AH66+XWN8bXq7l3RO/ukeaci98JfkbkxURZhtxV/HHuvUhnPLdX
3TwygPBYZFNo4pzVEhzWoTtnEtrFueKxyc3+LjZpuo+mBlQ6ORtfgkr9gBVphXZG
YEzkCD3lVdl8L4cw9BVpKrJCs1c5taGjdgdinqkbghm/fVvv96bJxc9x1tffXAcj
3OVdUN0UgXNCSaf/3A/phbeBQe9xS+3mpc4r6qvx+iy69mNBeNZ0xOitIjpjBo2+
dBEjSBwLk5q5tJqHmy/jKMJL4n9ROlx93XS+njxgibTvU6Fp9w+NOFD/HvxB3Tcz
6+jJF85D5BNAG3DBMKBjAoGBAOAxZvgsKN+JuENXsST7F89Tck2iTcQIT8g5rwWC
P9Vt74yboe2kDT531w8+egz7nAmRBKNM751U/95P9t88EDacDI/Z2OwnuFQHCPDF
llYOUI+SpLJ6/vURRbHSnnn8a/XG+nzedGH5JGqEJNQsz+xT2axM0/W/CRknmGaJ
kda/AoGANWrLCz708y7VYgAtW2Uf1DPOIYMdvo6fxib5i9zfisgcj/bbCUkFrhoH
+vq/5CIWxCPp0f85R4qxxQ5ihxJ0YDQT9Jpx4tmss4psavpabh3rxow5ohe+bYoQ
NE5OgEXk2wVfZczCZpigBKbKZHNYcelXttt/nP3rsCuGcM4h53s=
-----END RSA PRIVATE KEY-----
id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvqvp22wdktkyrtvp9eww6a8yvr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzuftdoklv6iedplqopkcmf0ayet2pkedo3mltbckfxpitamzf8djsifo9d8hfdov0iadx4o7ptixwkn5y2hmng0zqpyuecp4pzc6kivaihyfhilfr61rgl+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMzendkbuvxhmmbysdetk1rrgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYczrdk8jlqm8tehuc9c9whq== vagrant insecure public key

./dockrant/share/ — створимо файл phpinfo.php з phpinfo() функцією, щоб потім перевірити працездатність

phpinfo.php
<?php
phpinfo();

./dockrant/share/tools/ — покладемо кілька допоміжних скриптів для запуску PHP інтерпретаторів з під Docker exec PHPUnit (скачайте з сайту phpunit.phar

php56
#!/bin/bash
CMD="export IDE_PHPUNIT_PHPUNIT_PHAR='$IDE_PHPUNIT_PHPUNIT_PHAR'"
CMD+=" && export IDE_PHPUNIT_VERSION='$IDE_PHPUNIT_VERSION'"
CMD+=" && export SSH_CLIENT='$SSH_CLIENT'"
CMD+=" && export JETBRAINS_REMOTE_RUN='$JETBRAINS_REMOTE_RUN'"
CMD+=" && export DEBUG_CONFIG='$XDEBUG_CONFIG'"
CMD+=" && export XDEBUG_CONFIG='$XDEBUG_CONFIG'"
CMD+=" && php56 $@"
docker exec share_php_1 bash -c "$CMD"
php56tty
#!/bin/bash
CMD+="php56 $@"
docker exec -t -i share_php_1 bash -c "$CMD"
php70
#!/bin/bash
CMD="export IDE_PHPUNIT_PHPUNIT_PHAR='$IDE_PHPUNIT_PHPUNIT_PHAR'"
CMD+=" && export IDE_PHPUNIT_VERSION='$IDE_PHPUNIT_VERSION'"
CMD+=" && export SSH_CLIENT='$SSH_CLIENT'"
CMD+=" && export JETBRAINS_REMOTE_RUN='$JETBRAINS_REMOTE_RUN'"
CMD+=" && export DEBUG_CONFIG='$XDEBUG_CONFIG'"
CMD+=" && export XDEBUG_CONFIG='$XDEBUG_CONFIG'"
CMD+=" && php70 $@"
docker exec share_php_1 bash -c "$CMD"
php70tty
#!/bin/bash
CMD+="php70 $@"
docker exec -t -i share_php_1 bash -c "$CMD"

Для php* скриптів ми не використовуємо TTY, ці скрипти потрібні для коректної настройки інтеграції з IDE у використанні remote інтерпретаторів, скрипти php*tty потрібні для ручного використання запуску PHP скриптів, в тому числі і в інтерактивному режимі php -a.

./dockrant/vagrant/build/php/ — покладемо init.sh bash скрипт для копіювання файлів запуску PHP інтерпретаторів.

init.sh
#!/bin/bash
cp /share/tools/php56 /usr/bin/php56 && chmod +x /usr/bin/php56
cp /share/tools/php70 /usr/bin/php70 && chmod +x /usr/bin/php70
cp /share/tools/php56tty /usr/bin/php56tty && chmod +x /usr/bin/php56tty
cp /share/tools/php70tty /usr/bin/php70tty && chmod +x /usr/bin/php70tty

./dockrant/vagrant/build/docker/ — покладемо init.sh та docker-compose.sh bash скрипти для установки docker-compose і команд на складання контейнерів при піднятті гостьової ОС.

init.sh
#!/bin/bash
/usr/local/bin/docker-compose -f /share/docker-compose.yml build
/usr/local/bin/docker-compose -f /share/docker-compose.yml up -d
docker-compose.sh
#!/bin/bash
curl -L https://github.com/docker/compose/releases/download/1.8.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

Docker-compose
Створимо файл ./dockrant/share/docker-compose.yml

Тепер опишемо інструкції для створення docker-контейнерів, ми не будемо описувати інструкції для складання кожного образу, візьмемо готові.

Збираємо з наступних образів:

  • redis:3
  • percona:5
  • gurukami/php:5.6
  • gurukami/php:7.0 (для FPM використовується за замовчуванням)
  • gurukami/nginx
  • mongo:3
docker-compose.yml
version: '2'
services:
redis:
image: redis:3.0
mysql:
image: percona:5
environment:
- MYSQL_ROOT_PASSWORD=gurukami
volumes:
- /share:/share
php56:
image: gurukami/php:5.6
links:
- mysql
- mongo
- redis
volumes:
- /share:/share
- /home:/home
- /tmp/:/tmp/
php:
image: gurukami/php:7.0
links:
- mysql
- mongo
- redis
volumes:
- /share:/share
- /home:/home
- /tmp/:/tmp/
mongo:
image: mongo:3
ports:
- "27017:27017"
nginx:
image: gurukami/nginx:latest
depends_on:
- php
links:
- php
ports:
- "80:80"
- "443:443"
volumes:
- /share:/share

Vagrantfile
Створіть у папці dockrant файл Vagrantfile і запишіть туди наступні інструкції

Vagrantfile
Vagrant.require_version ">= 1.8.6"

required_plugins = %w(vagrant-hostsupdater)
plugins_to_install = required_plugins.select { |plugin| not Vagrant.has_plugin? plugin }
if not plugins_to_install.empty?
puts "Installing plugins: #{plugins_to_install.join(' ')}"
if system "vagrant plugin install #{plugins_to_install.join(' ')}"
exec "vagrant #{ARGV.join(' ')}"
else
abort "Installation of one or more plugins has failed. Aborting."
end
end

Vagrant.configure(2) do |config|

config.vm.box = "ubuntu/trusty64"
config.vm.hostname = "gurukami.local"

config.ssh.insert_key = false

config.hostsupdater.aliases = [
"sandbox.local"
]

config.nfs.map_uid = Process.uid
config.nfs.map_gid = Process.gid

config.vm.network :private_network, ip: "10.0.0.2"
config.vm.network :forwarded_port, guest: 22, host: 2202, id: "ssh"

config.vm.provider :virtualbox do |vb|
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
vb.name = "Gurukami (Dockrant)"
vb.memory = 1024
vb.cpus = 2
end

config.vm.provision "fix-no-tty", type: "shell" do |s|
s.privileged = false
s.inline = "sudo sed -i '/tty/!s/бемщ n/tty -s \\&\\& бемщ n/' /root/.profile"
end

config.vm.provision "shell", inline: 'mkdir /vagrant', run: "once"
config.vm.provision "shell", inline: 'echo "nameserver 8.8.8.8" >> /etc/resolv.conf', run: "always"
config.vm.provision "shell", path: './vagrant/build/php/init.sh', run: "once"
config.vm.provision "shell", path: './vagrant/build/docker/docker-compose.sh', run: "once"

config.vm.provision :docker
config.vm.provision "shell", path: './vagrant/build/docker/init.sh', run: "always"

config.vm.synced_folder ".", "/vagrant", disabled: true
config.vm.synced_folder "./share", "/share", nfs: true, nfs_udp: false
end


Тюнінг:

  • При необхідності шарінга можна додати опцію config.vm.network :public_network, щоб підняти на публічному інтерфейсі або vagrant share
  • Збільшити використання виділеної пам'яті vb.memory, за замовчуванням стоїть 1024 MB
  • Збільшити кількість використаних процесорів vb.cpus, за замовчуванням стоїть 2
Запуск
В папці dockrant запускаємо команду

vagrant up --provider virtualbox

Після складання відкриємо в браузері — sandbox.local/phpinfo.php


Docker-machine
Для того щоб наша віртуальна машина працювала як docker-machine нам необхідно додати її використовуючи generic драйвер, запускаємо з під папки dockrant

docker-machine create --driver generic --generic-ip-address=10.0.0.2 --generic-ssh-key ./ssh/id_rsa --generic-ssh-user vagrant sandbox

Після створення docker-machine, гостьову машину потрібно перезавантажити, т. к. після установки всі docker контейнери зупиняються

vagrant reload

PHP-CLI
Запуск PHP скриптів здійснюється на гостьовий машині (10.0.0.2), пам'ятайте, що між хост-машиною і гостьовий є /share папка.

php56 /path/to/file
php70 /path/to/file

Запуск PHP інтерпретаторів в інтерактивному режимі

php56tty -a
php70tty -a

Інтеграція з PHPStorm
Ми налаштуємо дебагер з допомогою XDebug, прикрутимо PHPUnit а також додамо управління нашими контейнерами через плагін Docker Integration, за допомогою якого можна буде дивитися логи наших сервісів, перезавантажувати контейнери, виконувати скрипти.

Додамо в налаштування наші PHP інтерпретатори, відкриваємо налаштування Languages & Frameworks → PHP



Додаємо спочатку 5.6 версію, потім повторюємо для версії 7.0, натискаємо на кнопку ...

Потім натиснувши на + вибираємо Remote...



У спливаючому вікні вибираємо тип Vagrant і вказуємо шлях до PHP інтерпретатора на гостьовій ОС /usr/bin/php56




Тепер додамо наш віддалений сервер в список для роботи з дебагером за запитом з веб-переглядача
Language & Frameworks → PHP → Servers. Пропишемо path mappings до /share папки щоб IDE зміг розпізнати запити по шляхах між хост машиною і гостьовий



Налаштуємо PHPUnit, йдемо в настройки Language & Frameworks → PHP → PHPUnit і для кожної версії PHP інтерпретатора пропишемо шлях до /share/tools/phpunit.phar





Ми майже готові до налагодження нашого додатка, але ще залишилося налаштувати конфігурації запуску


Налаштуємо віддалену налагодження PHP Remote Debug





Ставимо breakpoint наприклад у файлі phpinfo.php на 2 сходинці, запускаємо дебагер, переходимо в браузері на сторінку sandbox.local/phpinfo.php і бачимо, що наш дебагер спрацював в IDE







Тепер перейдемо до PHPUnit


Створимо простенький Unit test файл під іменем Test.php ./dockrant/share папці

Test.php
<?php

class Test extends PHPUnit_Framework_TestCase
{
public function testSomething()
{
$this->assertTrue(true);
}
}

Налаштуємо конфігурацію запуску



Запускаємо Unit test





Також можна запустити Unit test з дебагером





Тепер налаштуємо плагін Docker Integration, після установки плагіна необхідно додати нашу машину у налаштуваннях Build, Execution, Deployment → Docker як правило папки docker-machines лежать у вашій домашній директорії користувача, нам потрібен sandbox docker-machine який ми створювали по інструкції вгорі використовуючи generic драйвер



Внизу вкладка Docker буде показано після перезавантаження IDE



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

Розгортання оточення було протестовано на:

  • Windows 10
  • MacOS Sierra 10.12
  • Ubuntu 14.04 Desktop
Спасибі за прочитання, сподіваюся ця стаття допоможе вам організувати зручне оточення.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.