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.
For this step, just go to https://docs.docker.com/get-docker/ and follow the instructions for yours OS.
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.
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.
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.
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"
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
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
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
Expanding our server
Now let's add a database for our project, here we use
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
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.
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 an Mac with M1 processor like me:
Quick DB edit
If we need something to edit/view our database, we can add
So we add a new service:
phpmyadmin: image: phpmyadmin restart: always ports: - 8080:80
We map it to port 8080. All done.
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
That's it!. Now you can enjoy a nice multi-version PHP development environment for your projects always ready when you need it.