Multiple PHP versions on a host using Docker

    Often, PHP developers are faced with the task of testing the operation of a web application for several interpreter versions. It can be solved in different ways. You can tritely install different versions of PHP on one host, but this is fraught with library conflicts and other difficulties. The second extreme is to make several isolated virtual machines with different environments, but one cannot do without excessive use of hardware resources and wasting time on deploying the working environment. At the moment, this task can be solved most easily with the help of Docker.

    image

    Below, I will describe a working solution for Ubuntu 18, where the stack is Nginx + PHP-FPM. This solution is easily scaled: a container with PHP-FPM takes up only 300 MB in memory, and you can add containers with other versions of the interpreter with three commands (or, depending on preferences of even one, run). The second plus of this solution is that the developer does not need to switch the web server between interpreters, since they are already separated into different containers (the application code is used the same).

    Addition: Judging by the comments, some readers did not understand for what cases the described solution is suitable. Therefore, I want to note that all of the following is intended to be used EXCLUSIVELY at the developer’s workstation, and may also be suitable for a stage server with some reservations.

    So, let's begin…

    1. Install 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. Install the containers with the necessary versions of PHP


    As an example of creating a working environment, PHP versions 7.1 and 7.2 from the official Docker repository PHP are used . By analogy, if you have an image, you can install any version of 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 by default runs on port 9000. When creating images, we published the 9000th container ports on the free 9071 and 9072 ports of the host machine (the numbers are taken arbitrarily from the unprivileged range). Next we will be proxying requests for PHP processing to these ports (the fastcgi_pass parameter in the Nginx virtual host configuration).

    Also it was necessary to forward the directory with the projects (/ var / www) inside the containers, otherwise PHP-FPM swears that it does not see the files (if you know how to make this moment better / more correctly, then write in the comments).

    We check that the containers are running, and the ports are published correctly:

    sudo docker ps -a
    sudo netstat -lpn


    3. Configure the environment for virtual hosts


    Add the following lines to / etc / hosts:
    127.0.0.1    project.local.php71  ### php 7.1
    127.0.0.1    project.local.php72  ### php 7.2

    Create a directory for the project:

    sudo mkdir -p /var/www/project.local
    echo'<?php phpinfo(); ?>' | sudo tee /var/www/project.local/index.php
    

    I took the name for the project (project.local) and virtual hosts (project.local.php71 / 72) arbitrarily, but you can use names that are convenient for you (just remember to change the settings for virtual hosts).

    Initially, only one phpinfo command was put in the index file, after setting up and verifying the system’s performance, index.php will need to be replaced with the one used in the project.

    4. Install nginx and configure virtual hosts


    sudo apt install nginx

    Create the file /etc/nginx/sites-available/project.local.php71 with the description of the first virtual host (it will be used to test the project under 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;
      }
    }
    

    Similarly, the /etc/nginx/sites-available/project.local.php72 file for the second virtual host:

    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;
      }
    }

    Now we make symlinks to the above configurations of virtual hosts and reboot 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. Check


    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,\}"

    As a result, we should get the PHP version (as a result of processing phpinfo commands by interpreters of different versions).

    Now it only remains to upload your project to the /var/www/project.local folder and you can check its work in the PHP 7.1 interpreter at http: //project.local.php71 and PHP 7.2 at http: //project.local.php71 .

    Additional Resources
    1. The Complete Docker Practical Guide

    Also popular now: