My other article about web development via the MAMP stack in Docker is the most popular article of this website to date. That’s great! It feels good to give back to the community from which I learned so much over tha past 15 years! This article is a follow up when using a custom PHP8 Docker image.
Extend PHP8 for Docker MAMP development
In the other article I describe a way to use Docker’s docker-compose.yml
file to easily get a MAMP stack started, even with phpmyadmin! Lately I wanted to move to PHP8, since I want to keep on track with latest features and so I searched Docker hub for an image containing PHP8 and Apache. The image I found was PHP’s default for version 8 so I updated my docker-compose.yml
file to install it.
This would of course be a test to prove the flexibility of Docker: you drop one image containing a certain version, in favour of a new version and off you go! This turned out a little harder than expected.
The hassle had nothing to do with Docker itself, as changing the docker-compose.yml
file and rebuild the images was sufficient to get it all running again. But soon I discovered that the image of PHP8 lacked certain extensions I needed: I was unable to connect to MySQL via mysqli and I could not modify images with the gd extension.
I decided to write a custom PHP.Dockerfile
in order to have the default image extended with what I needed, and then update the docker-compose.yml
file to let it be used in my MAMP setup.
FROM php:8.0-apache
ENV PHP_EXTRA_CONFIGURE_ARGS="--with-apxs2 --disable-cgi --with-zip"
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
libicu-dev \
libzip-dev \
&& a2enmod rewrite \
&& docker-php-ext-install mysqli \
&& docker-php-ext-install exif \
&& docker-php-ext-install bcmath \
&& docker-php-ext-install intl \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install gd \
&& docker-php-ext-install zip \
&& chsh -s /bin/bash www-data \
&& rm -rf /var/lib/apt/lists/*
CMD ["apache2-foreground"]
So in short, the above Dockerfile will grab the image named 8.0-apache
from PHP’s Docker hub account page, will add some additional arguments. Then apt
is used to add additional dependencies. First a set of dependencies for PHP extensions, then Apache’s mod_rewrite
as I want to use it in my Apache configuration, followed by php extensions I want to add. So far so good; the image is nicely built.
But now for the docker-compose.yml
file. How do I need to modify it to let it use a local Dockerfile
instead of retrieving something from the hub? It was a bit of a puzzle, and I made few mistakes in the depth of properties, but in the end the following did the trick: define a build
property with two childeren being context
and dockerfile
. These two together tell docker-compose
to look in the current directory for the desired Dockerfile
, in this case PHP.Dockerfile
.
version: '3'
services:
web:
build:
context: .
dockerfile: ./PHP.Dockerfile
ports:
- '80:80'
volumes:
- /Users/vincentb/Sites/_docker/apache:/etc/apache2/sites-enabled
- /Users/vincentb/Sites:/var/www/html
- /Users/vincentb/Sites/_docker/php/php.ini:/usr/local/etc/php/php.ini
depends_on:
- mariadb
extra_hosts:
- 'ax710.test:127.0.0.1'
# - 'some-other-host.test:127.0.0.1'
networks:
- dev-env
phpmyadmin:
image: phpmyadmin:latest
ports:
- 8080:80
environment:
- PMA_ARBITRARY=1
- PMA_HOST=mariadb
depends_on:
- mariadb
volumes:
- /Users/vincentb/Sites/_docker/php/php.ini:/usr/local/etc/php/php.ini
networks:
- dev-env
mariadb:
image: mariadb:latest
restart: always
environment:
MYSQL_ROOT_PASSWORD: 'secret'
MYSQL_USER: 'vincentb'
MYSQL_PASSWORD: 'secret'
MYSQL_DATABASE: 'vincentb'
volumes:
- mysqldata:/var/lib/mysql
ports:
- 3306:3306
networks:
- dev-env
volumes:
mysqldata: {}
networks:
dev-env: {}
OK, cool! All set! Now call the following on your command line and the new PHP image should be built and you’re ready to go.
docker-compose -f ./docker-compose.yml up -d
So to conclude: Docker has proven to be flexible! My machine is not polluted with all kinds of packages all over the place, but everything lives in a directory from Docker, where you can easily do a cleanup from. Switching versions is easy, though it was a bit of a hassle to configure docker-compose.yml
in combination with a local Dockerfile
. Since I now know this, I will probably often use this to locally orchestrate a setup of docker-compose.yml
with several Dockerfile
s.