Часто перед разработчиками PHP встаёт задача проверить работу веб-приложения под несколько версий интерпретатора. Решить её можно разными способами. Можно банально установить разные версии PHP на один хост, но это чревато конфликтами библиотек и другими сложностями. Вторая крайность — сделать несколько изолированных виртуальных машин с разным окружением, но здесь не обойтись без чрезмерного использования аппаратных ресурсов и излишней траты времени на разворачивание рабочего окружения. На настоящий момент наиболее просто решить данную задачу можно с помощью Docker.
Ниже я опишу рабочее решение под Ubuntu 18, где в качестве стека используется связка Nginx + PHP-FPM. Данное решение легко масштабируется: контейнер с PHP-FPM занимает всего 300 Мб в памяти, а добавить контейнеры с другими версиями интерпретатора можно тремя командами (или в зависимости от предпочтений даже одной — run). Второй плюс этого решения в том, что разработчику не нужно переключать веб-сервер между интерпретаторами, так как они уже разнесены в разные контейнеры (код приложения при этом используется один и тот же).
Итак, начнём…
1. Устанавливаем Docker
sudo apt update
sudo apt install ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
sudo apt install docker-ce
2. Устанавливаем контейнеры с нужными версиями PHP
В качестве примера создания рабочего окружения использованы PHP версий 7.1 и 7.2 из официального Docker-репозитория PHP. По аналогии при наличии образа можно установить какие угодно версии PHP:
sudo docker pull php:7.1.25-fpm-stretch
sudo docker create --name=fpm71 -p 127.0.0.1:9071:9000 -v /var/www:/var/www php:7.1.25-fpm-stretch
sudo docker start fpm71
sudo docker pull php:7.2.13-fpm-stretch
sudo docker create --name=fpm72 -p 127.0.0.1:9072:9000 -v /var/www:/var/www php:7.2.13-fpm-stretch
sudo docker start fpm72
PHP-FPM по умолчанию работает на 9000 порту. При создании образов мы опубликовали 9000-е порты контейнеров на свободные 9071 и 9072 порты хост-машины (номера взяты произвольно из непривилегированного диапазона). Далее на эти порты мы будем проксировать запросы на обработку PHP (параметр fastcgi_pass в конфигурации виртуальных хостов Nginx).
Также понадобилось пробросить внутрь контейнеров каталог с проектами (/var/www), иначе PHP-FPM ругается, что не видит файлов (если знаете, как сделать этот момент лучше/правильней, то пишите в комментарии).
Проверяем, что контейнеры запущены, а порты опубликованы правильно:
sudo docker ps -a
sudo netstat -lpn
3. Настраиваем окружение для виртуальных хостов
Добавляем в /etc/hosts строки:
127.0.0.1 project.local.php71 ### php 7.1
127.0.0.1 project.local.php72 ### php 7.2
Создаём каталог для проекта:
sudo mkdir -p /var/www/project.local
echo '<?php phpinfo(); ?>' | sudo tee /var/www/project.local/index.php
Название для проекта (project.local) и виртуальных хостов (project.local.php71/72) я взял произвольно, но вы можете использовать удобные для вас названия (только не забудьте при этом поменять настройки виртуальных хостов).
Изначально в индексный файл была положена только одна команда phpinfo, после настройки и проверки работоспособности системы, index.php нужно будет заменить на тот, что используется в проекте.
4. Устанавливаем nginx и настраиваем виртуальные хосты
sudo apt install nginx
Создаём файл /etc/nginx/sites-available/project.local.php71 с описанием первого виртуального хоста (он будет использоваться для проверки работы проекта под PHP v.7.1):
server {
listen 80;
server_name project.local.php71;
index index.php;
root /var/www/project.local;
location / {
try_files $uri $uri/ =404;
}
location ~ .php$ {
fastcgi_pass 127.0.0.1:9071;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Точно так же файл /etc/nginx/sites-available/project.local.php72 для второго виртуального хоста:
server {
listen 80;
server_name project.local.php72;
index index.php;
root /var/www/project.local;
location / {
try_files $uri $uri/ =404;
}
location ~ .php$ {
fastcgi_pass 127.0.0.1:9072;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Теперь делаем симлинки на вышесозданные конфигурации виртуальных хостов и перегружаем Nginx:
cd /etc/nginx/sites-enabled
sudo ln -s ../sites-available/project.local.php71
sudo ln -s ../sites-available/project.local.php72
sudo systemctl reload nginx
5. Проверяем
curl --silent http://project.local.php71/index.php | grep -o "PHP Version [0-9.]{1,}"
curl --silent http://project.local.php72/index.php | grep -o "PHP Version [0-9.]{1,}"
В качестве результата мы должны получить версию PHP (как результат обработки команды phpinfo интерпретаторами разных версий).
Теперь осталось лишь залить свой проект в папку /var/www/project.local и можно проверять его работу в интерпретаторе PHP 7.1 по адресу http://project.local.php71 и PHP 7.2 по http://project.local.php71.
Дополнительные материалы
1. Полное практическое руководство по Docker
Автор: o-pod