Daniel Stokes

How to assemble the best PHP docker image

November 27th 2019 2:15pm
Updated: November 27th 2019 4:15pm

Picking the right php docker image can be a difficult process. Often the image is missing features that you need or has unused features. Where do we start?

Picking a base image

alpine? fpm? cli? zts? apache? What do these mean and which one should I choose?

Well the php docker hub page has an overview of each variation if you scroll down. Here is a summary I pulled directly from that page 1:

CLI: This variant contains the PHP CLI tool with default mods. If you need a web server, this is probably not the image you are looking for.

Apache: This image contains Debian's Apache httpd in conjunction with PHP (as mod_php) and uses mpm_prefork by default.

FPM: This variant contains PHP-FPM, which is a FastCGI implementation for PHP. In order to use this image variant, some kind of reverse proxy (such as NGINX, Apache, or other tool which speaks the FastCGI protocol) will be required.

Alpine: This image is based on the popular Alpine Linux project, available in the alpine official image. Alpine Linux is much smaller than most distribution base images (~5MB), and thus leads to much slimmer images in general.


For my project I chose fpm. The requirement of a reverse proxy is fine because my application uses another docker container for that.

Specify a version

Its very important that you specify a version of php. Each version will support different features. I recommend picking the latest stable release and sticking with it. When new versions come out set aside some time to test out the new version before switching over. Some features might need recoding for newer versions so specifying latest instead of a particular version number could be dangerous.

Create a separate Dockerfile

To take full advantage of docker and docker-compose you will want to customize your docker image with a Dockerfile. The Docker website has quite a lot of documentation on how to write these files which can be found here. This file is a set of instructions for building the image, with it you can: create a particular folder structure, install extensions, run commands, set environment variables, create users and permissions. The list goes on. Its really quite powerful but also can be overwhelming at first.

Installing the right extensions

To make sure your php image meets the requirements of your application you will want to compare the requirements with what is already installed and add any additional extensions that are missing in your docker file.

The oficial documentation recommends you run php -m or php -i to see what extensions are already included before installing any additional ones.

If you are using a framework, the php extension requirements will most likely be listed on the installation instructions page. I'm using the Laravel framework. Laravel 5.8 requirements are listed here. You can cross reference that list with this list of dockerfile extension commands to install all the right extensions. That combined with the

docker-php-ext-install

command will install the extension. Some extensions may require additional packages and configuration so you may need to run

RUN apt-get update && apt-get install 

before docker-php-ext-install

and to configure run this after

docker-php-ext-configure


I have found the best way to learn is by example so I will include my php dockerfile for laravel that includes additional extensions for the GD library. I built this file off of a few files I found online.

Dockerfile

	FROM php:7.2-fpm

# Copy composer.lock and composer.json
COPY composer.lock composer.json /var/www/

# Set working directory
WORKDIR /var/www

# Install dependencies
RUN apt-get update 
RUN apt-get install libcurl3-dev
RUN apt-get install -y libxml2-dev
RUN apt-get install -y libpq-dev 
RUN apt-get install -y libfreetype6-dev \
	libwebp-dev \
	libjpeg62-turbo-dev \
	libpng-dev \
	nano \
	libgmp-dev
RUN apt-get install -y git 
RUN apt-get install -y \
    zlib1g-dev \
    libzip-dev
RUN apt-get install -y unzip 


RUN docker-php-ext-install curl
RUN docker-php-ext-install bcmath
RUN docker-php-ext-install ctype
RUN docker-php-ext-install json
RUN docker-php-ext-install mbstring
RUN docker-php-ext-install pdo
RUN docker-php-ext-install pdo_pgsql
RUN docker-php-ext-install tokenizer
RUN docker-php-ext-install xml

RUN docker-php-ext-install exif

RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-webp-dir=/usr/include/  --with-jpeg-dir=/usr/include/
RUN docker-php-ext-install gd
RUN docker-php-ext-install zip
# RUN docker-php-ext-install pgsql

# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Add user for laravel application
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www

# Copy existing application directory contents
COPY . /var/www

# Copy existing application directory permissions
COPY --chown=www:www . /var/www

# Change current user to www
USER www

# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]
	

Hopefully that code and explanation was helpful. This code also installs php composer and creates a user and group.

Links:

1https://hub.docker.com/_/php/

https://laravel.com/docs/5.8#server-requirements

https://gist.github.com/chronon/95911d21928cff786e306c23e7d1d3f3


Comments