Creating an apache-php-composer docker container for development
So I'm in need of a repeatable environment setup for developing PHP projects. I've seen package setups like XAMPP and MAMP, but I'd like to be closer to the production environment which uses Docker containers for all services.
Requirements
The base VM is Ubuntu 20.04.1 LTS
Docker-CE version 20.10.16 installed
Pull the base image
The base container image is the php:8.0-apache image from Docker Hub. As the name and tag imply, the image runs the apache web server and has php 8.0 installed and configured.
~$ docker pull php:8.0-apache
8.0-apache: Pulling from library/php
a603fa5e3b41: Pull complete
c428f1a49423: Pull complete
156740b07ef8: Pull complete
fb5a4c8af82f: Pull complete
25f85b498fd5: Pull complete
9b233e420ac7: Pull complete
fe42347c4ecf: Pull complete
9a7bf1523229: Pull complete
a0b541d575c5: Pull complete
c0e75b0cc4dc: Pull complete
a97a86207955: Pull complete
f88820a52a78: Pull complete
81ebcb8aedf6: Pull complete
Digest: sha256:2fd39b3d456959fa399e6dc3db28ccfbb518e6ca5727cd6f2553f338ba8a8847
Status: Downloaded newer image for php:8.0-apache
docker.io/library/php:8.0-apache
~$
Install Composer
Now that we have our base container we need to install Composer for managing PHP dependancies. We need the following Dockerfile for building our new image. The RUN commands come from the Composer download page.
FROM php:8.0-apache
RUN cd /var/tmp && php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN cd /var/tmp && php -r "if (hash_file('sha384', 'composer-setup.php') === '55ce33d7678c5a611085589f1f3ddf8b3c52d662cd01d4ba75c0ee0459970c2200a51f492d557530c71c15d8dba01eae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
RUN cd /var/tmp && php composer-setup.php
RUN cd /var/tmp && php -r "unlink('composer-setup.php');"
RUN cd /var/tmp && mv composer.phar /usr/local/bin/composer
The new image is built with the docker build command. Let's give it the tag 8.0-apache-composer.
~/tmp$ docker build -t php:8.0-apache-composer .
Sending build context to Docker daemon 2.56kB
Step 1/6 : FROM php:8.0-apache
---> b6af81e9f77f
Step 2/6 : RUN cd /var/tmp && php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
---> Running in f910ad74f689
Removing intermediate container f910ad74f689
---> f210701f81b3
Step 3/6 : RUN cd /var/tmp && php -r "if (hash_file('sha384', 'composer-setup.php') === '55ce33d7678c5a611085589f1f3ddf8b3c52d662cd01d4ba75c0ee0459970c2200a51f492d557530c71c15d8dba01eae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
---> Running in 80e4dec0b876
Installer verified
Removing intermediate container 80e4dec0b876
---> f09bf1368b59
Step 4/6 : RUN cd /var/tmp && php composer-setup.php
---> Running in c05e8dff581c
All settings correct for using Composer
Downloading...
Composer (version 2.4.4) successfully installed to: /var/tmp/composer.phar
Use it: php composer.phar
Removing intermediate container c05e8dff581c
---> 6922990b4d30
Step 5/6 : RUN cd /var/tmp && php -r "unlink('composer-setup.php');"
---> Running in 6354ff1806e4
Removing intermediate container 6354ff1806e4
---> af37f1ef5ea2
Step 6/6 : RUN cd /var/tmp && mv composer.phar /usr/local/bin/composer
---> Running in b15ea6a61156
Removing intermediate container b15ea6a61156
---> 6554b5c2ae90
Successfully built 6554b5c2ae90
Successfully tagged php:8.0-apache-composer
~/tmp$
Now we can see we have our new container image with docker images:
~/tmp$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
php 8.0-apache-composer 6554b5c2ae90 48 seconds ago 461MB
php 8.0-apache b6af81e9f77f 5 days ago 455MB
~/tmp$
Verify Composer is installed
Let's start a container and run the composer command to verify composer is installed. The --rm flag tells docker to delete the container once we have exited from it.
~/tmp$ docker run --rm -it php:8.0-apache-composer bash
root@426a49724a79:/var/www/html# composer --version
Composer version 2.4.4 2022-10-27 14:39:29
root@426a49724a79:/var/www/html# exit
exit
~/tmp$
or more simply:
~/tmp$ docker run --rm php:8.0-apache-composer composer --version
Composer version 2.4.4 2022-10-27 14:39:29
~/tmp$
Setup the new project
The php container is configured to use /var/www/html as the apache DocumentRoot. To keep the project files persistent we will mount this directory to a project directory on the host. This is also the second project being developed on this host so port 81 will be mapped to the container port 80.
~$ mkdir ~/project2-site-query-app
~$ docker run -d --name php-site-query -v ~/project2-site-query-app:/var/www/html -p 81:80 php:8.0-apache-composer
9ce71bb3f5a9bb86de046a9ab1c853b6961e56f59a53cf05090272b36ce00bf9
~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9ce71bb3f5a9 php:8.0-apache-composer "docker-php-entrypoi…" 8 seconds ago Up 7 seconds 0.0.0.0:81->80/tcp, :::81->80/tcp php-site-query
643e59316cc0 php:8.0-apache "docker-php-entrypoi…" 21 hours ago Up 21 hours 0.0.0.0:80->80/tcp, :::80->80/tcp php-stock-quotes
~$
Verify the container is serving PHP
Finally, add a simple PHP file to the project directory and get data from it.
~$ cd project2-site-query-app/
rob@xubuntu2004:~/project2-site-query-app$ echo '<?php phpinfo(); ?>' >index.php
~/project2-site-query-app$
~/project2-site-query-app$ curl http://localhost:81 2>/dev/null | grep "</td>" | grep 'PHP Version'
<tr><td class="e">PHP Version </td><td class="v">8.0.26 </td></tr>
~/project2-site-query-app$
Or verify with a browser if you'd like.
