Set up a development environment with multiple PHP versions using Docker
Since I've moved away from PHP I did not work on it much. Lately, however, I had to touch an old project (using PHP 5.6) and a new one in 7.4.
I got a new Apple laptop (an M1) and I had no intention to spend time installing different versions of PHP, so instead I made a small service using Docker to have a ready environment to work on.
Install Docker
For this step, just go to https://docs.docker.com/get-docker/ and follow the instructions for yours OS.
Let's start
We are going to use docker-compose
and, in total, we need few folders and 3 files.
First, create a new folder, that will be your project root:
Inside, create 3 files:
Dockerfile.74
: This will be your Dockerfile for PHP 7.4.
Dockerfile.56
: This will be your Dockerfile for PHP 5.6.
docker-compose.yml
: This will contain our environment configuration.
Docker.74
The content of this file should be like this:
FROM php:7.4-apache
RUN docker-php-ext-install mysqli
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
So what we do here is this: FROM php:7.4-apache
will create the container for PHP 7.4, using apache. On next line RUN docker-php-ext-install mysqli
will add extensions to PHP, in this case we add mysqli for a later connection to a database.
You can add what you need for your project, for example, RUN docker-php-ext-install mysqli pdo zip
to have PDO and ZIP extension activated as well.
Lastly, RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini
copies the production version of php.in
to be used by the container. You can remove this line if you prefer the standard PHP configuration.
Docker.56
This is basically identical to the Docker.74
, only changing the container.
FROM php:5.6-apache
RUN docker-php-ext-install mysqli
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
docker-compose.yml
Now let's write our docker-compose.yml
file. Starting from the first service, add
version: '3.8'
services:
php74:
build:
context: .
dockerfile: Dockerfile.74
ports:
- 80:80
volumes:
- ./php74:/var/www/html/
Here we name our service php74
and connect it to our Dockerfile.74
file. Next, we map to port 80
and add a volume to store our files. Create a new folder called php74
on your project root, anything in it be loaded on our PHP 7.4 server. inside you can place a test file, info.php
, and add the following line inside:
<?php phpinfo(); ?>
At this point, we can do a quick test. On terminal, cd to the project folder and run
docker-compose up
Then on your browser go to http://localhost:80/info.php
. The PHP info page should load and confirming you are running version 7.4.
All right, stop the process and lets continue. Next we add the PHP 5.6 server, same under services
:
php56:
build:
context: .
dockerfile: Dockerfile.56
ports:
- 88:80
volumes:
- ./php56:/var/www/html/
Same as before, create a folder called a php56
and inside put a copy of the info.php
file. This time we map to port 88
, so if we want to run for a test it again, the URL for our PHP 5.6 server will be http://localhost:88/
.
Expanding our server
Now let's add a database for our project, here we use mysql
:
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
volumes:
- ./mysql:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password #example of a password
Here we use directly an image
instead of a Dockerfile
. We add a restart: always
to make it restart if it stops and then we set volumes
.
Let's create a new folder mysql
in our project root. This will prevent our databases from being destroyed when the server stop. Then we map it to /var/lib/mysql
directory on our db container.
Finally, we add a password with an environment variable; Not much security needed here so we use the word password
. You can change it.
If you need to edit your mysql
configuration, you can append another volume and connect it to a file.
- ./configs/my.cnf:/etc/my.cnf
You can do the same for your PHP configuration, if needed.
For Mac M1
mysql
image needs the following line added to the configuration if you have a Mac with M1 processor like me:
platform: linux/x86_64
Quick DB edit
If we need something to edit/view our database, we can add phpmyadmin
.
So we add a new service:
phpmyadmin:
image: phpmyadmin
restart: always
ports:
- 8080:80
We map it to port 8080. All done.
Now your docker-compose.yml
file should look like this:
version: '3.8'
services:
php74:
build:
context: .
dockerfile: Dockerfile.74
ports:
- 80:80
volumes:
- ./php74:/var/www/html/
php56:
build:
context: .
dockerfile: Dockerfile.56
ports:
- 88:80
volumes:
- ./php56:/var/www/html/
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
volumes:
- ./volumes/mysql:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password #example of a password
phpmyadmin:
image: phpmyadmin
restart: always
ports:
- 8080:80
We can finally run our environment. Let's use docker-compose up
again and we can access the following domains:
http://localhost:80/
: Our PHP 7.4 domain.
http://localhost:88/
: Our PHP 5.6 domain.
http://localhost:8080/
: Our PHPMyAdmin domain.
To connect to the database from any of your apps, just use the name db
(the database service name) as host and root
as user. The password will be what is added on MYSQL_ROOT_PASSWORD
line.
That's it!. Now you can enjoy a nice multi-version PHP development environment for your projects always ready when you need it.