Docker поменять версию php

Updating PHP 5 (or any other) Apps with Docker

PHP5, released in 2014, has reached its end of life in 2018, but many hosters continued to support it. If you have any custom PHP applications, you might still be running them on a server that has a PHP5 runtime.

The upgrade path for these applications might not be obvious, but I found a way that should make it easier, so in this article we’re going to have a look at running PHP simultaneously with PHP5 and PHP7 using docker and docker-compose .

PHP 7 Breaking Changes

PHP 7 introduced lots of breaking changes like different variable accessing, foreach loops and also deprecating and removing functions like:

  • call_user_method()
  • call_user_method_array()
  • ereg() — Regular expression match
  • eregi() — Case insensitive regular expression match
  • ereg_replace() — Replace regular expression
  • eregi_replace() — Replace regular expression case insensitive

Alright, so this means that we need to take all those functions and replace them with their new and improved counterpart, enter Docker!

Here’s the example PHP code we’ll use in this example ( index.php ):

 // will not work in PHP7 $string = 'XYZ'; if (eregi('z', $string)) < echo "'$string' contains a 'z' or 'Z'!"; > // will work in PHP7 $string_new = 'XZY'; preg_match('/z|Z/', $string_new, $matches); if(count($matches)>0)< echo "'$string_new' contains a 'z' or 'Z'!"; > ?> 

Docker PHP5 / PHP7 in parallel

For my case, I needed to port some code from PHP5 to PHP7, because running outdated software is an easy security vulnerability.

I needed a way to run the code in parallel with different PHP versions, to be sure that A: it still works, and B: it works as it did before.

Even though some changes are breaking like the removal of the eregi() function, the alternative function that you’re supposed to use, already works fine on PHP5.

So basically what I had to do was to get it running in both versions (for the most part). I created two directories for the different Dockerfiles and then used docker-compose up to run them both at once.

The Dockerfiles for the different PHP versions we can lock by the following differences:

# Base image FROM php:5.6-apache 
# Base image FROM php:7.3-apache 

The full Dockerfiles are pasted below.

Docker Compose: Mounting the Code

To mount our code into the different containers we’ll make use of the volumues property of our services. Lest’s have a look at our docker-compose.yml and break it down below:

version: "3.1" services: web1: build: docker/php5-6-apache2 container_name: php5-container volumes: - ./php-project-src:/var/www/html/public ports: - "8080:80" web2: build: docker/php7-3-apache2 container_name: php7-container volumes: - ./php-project-src:/var/www/html/public ports: - "8081:80" 

As you can see it has two nearly identical sections describing the services web1 and web2 , which both mount the source code from the php-project-src directory into the container’s web server directory at /var/www/html/public and they each get their own Dockerfile from the different directory through the build property.

If I know run docker-compose up , I get the output of both docker containers and they’re listening on localhost:8080 and localhost:8081 .

Starting php5-container . done Starting php7-container . done Attaching to php7-container, php5-container php5-container | [Sun Feb 09 21:12:13.770033 2020] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.25 (Debian) PHP/5.6.40 configured -- resuming normal operations php5-container | [Sun Feb 09 21:12:13.770070 2020] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND' php7-container | [Sun Feb 09 21:12:13.782147 2020] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.38 (Debian) PHP/7.3.11 configured -- resuming normal operations 

In my browser I can now see that the PHP7 container at port 8081 is not happy with me attempting to use the horrible and deprecated eregi function:

Fatal error: Uncaught Error: Call to undefined function eregi() in /var/www/html/public/index.php:5 Stack trace: #0 thrown in /var/www/html/public/index.php on line 5 

While at http://localhost:8080 everything is tip top and the output is:

'XYZ' contains a 'z' or 'Z'! 'XZY' contains a 'z' or 'Z'! 

That’s it, now we can work on the source code, comment and uncomment parts and hack away until our project is fully ported to PHP7!

If you found this useful, consider saying hello on twitter or joining a code stream on twitch 🙂

Full PHP5, PHP7 Dockerfiles

# Base image FROM php:5.6-apache # Fix debconf warnings upon build ARG DEBIAN_FRONTEND=noninteractive # Run apt update and install some dependancies needed for docker-php-ext RUN apt update && apt install -y apt-utils sendmail mariadb-client pngquant unzip zip libpng-dev libmcrypt-dev git \ curl libicu-dev libxml2-dev libssl-dev # Install PHP extensions # RUN docker-php-ext-install mysqli bcmath gd intl xml curl pdo_mysql pdo_sqlite hash zip dom session opcache # Update web root to public # See: https://hub.docker.com/_/php#changing-documentroot-or-other-apache-configuration ENV APACHE_DOCUMENT_ROOT /var/www/html/public RUN sed -ri -e 's!/var/www/html!$!g' /etc/apache2/sites-available/*.conf RUN sed -ri -e 's!/var/www/!$!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf # Enable mod_rewrite RUN a2enmod rewrite 
# Base image FROM php:7.3-apache # Fix debconf warnings upon build ARG DEBIAN_FRONTEND=noninteractive # Run apt update and install some dependancies needed for docker-php-ext RUN apt update && apt install -y apt-utils sendmail mariadb-client pngquant unzip zip libpng-dev libmcrypt-dev git \ curl libicu-dev libxml2-dev libssl-dev sqlite3 # Install PHP extensions RUN docker-php-ext-install mysqli bcmath gd intl xml pdo_mysql hash dom session opcache # Update web root to public # See: https://hub.docker.com/_/php#changing-documentroot-or-other-apache-configuration ENV APACHE_DOCUMENT_ROOT /var/www/html/public RUN sed -ri -e 's!/var/www/html!$!g' /etc/apache2/sites-available/*.conf RUN sed -ri -e 's!/var/www/!$!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf # Enable mod_rewrite RUN a2enmod rewrite 

Thank you for reading! If you have any comments, additions or questions, please tweet or toot them at me!

Источник

Несколько версий PHP на хосте с помощью Docker

Часто перед разработчиками PHP встаёт задача проверить работу веб-приложения под несколько версий интерпретатора. Решить её можно разными способами. Можно банально установить разные версии PHP на один хост, но это чревато конфликтами библиотек и другими сложностями. Вторая крайность — сделать несколько изолированных виртуальных машин с разным окружением, но здесь не обойтись без чрезмерного использования аппаратных ресурсов и излишней траты времени на разворачивание рабочего окружения. На настоящий момент наиболее просто решить данную задачу можно с помощью Docker.

image

Ниже я опишу рабочее решение под 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. Настраиваем окружение для виртуальных хостов

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 '' | sudo tee /var/www/project.local/index.php 

Название для проекта (project.local) и виртуальных хостов (project.local.php71/72) я взял произвольно, но вы можете использовать удобные для вас названия (только не забудьте при этом поменять настройки виртуальных хостов).

Изначально в индексный файл была положена только одна команда phpinfo, после настройки и проверки работоспособности системы, index.php нужно будет заменить на тот, что используется в проекте.

4. Устанавливаем nginx и настраиваем виртуальные хосты

Создаём файл /etc/nginx/sites-available/project.local.php71 с описанием первого виртуального хоста (он будет использоваться для проверки работы проекта под PHP v.7.1):

Точно так же файл /etc/nginx/sites-available/project.local.php72 для второго виртуального хоста:

Теперь делаем симлинки на вышесозданные конфигурации виртуальных хостов и перегружаем 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\.]\" curl --silent http://project.local.php72/index.php | grep -o "PHP Version [0-9\.]\" 

В качестве результата мы должны получить версию PHP (как результат обработки команды phpinfo интерпретаторами разных версий).

Теперь осталось лишь залить свой проект в папку /var/www/project.local и можно проверять его работу в интерпретаторе PHP 7.1 по адресу http://project.local.php71 и PHP 7.2 по http://project.local.php71.

Источник

Читайте также:  Python remove from setup
Оцените статью