How to install additional PHP extensions
We provide a number of PHP packages by default, but there will be times where you'll need to add additional PHP extensions in order to support a certain PHP library in your application. By default, we've included a popular tool called install-php-extensions
that allows you to install almost any PHP module that you'll need.
Installing extensions is easy. All you need to do is find the extension you'd like to install on the docker-php-extension installer README. Once you have the name of the extensions, you'll need to add it to the Dockerfile
in your project.
Our images are unprivileged by default. This means you'll need to switch to root
to do "root things", then switch back to the www-data
user. This ensures your container image is hardened against security vulnerabilities.
Example: Installing the "intl" extension
FROM serversideup/php:8.2.12-fpm-nginx-bookworm
# Switch to root so we can do root things
USER root
# Install the intl extension with root permissions
RUN install-php-extensions intl
# Drop back to our unprivileged user
USER www-data
It's really that simple. The install-php-extensions
tool will automatically install the operating system packages that are required for the PHP extension to work and add the extension to PHP.
For more details on this script, we encourage you to check out the GitHub repository for this project.
View the "docker-php-extension-installer" Project on GitHub →
Docker Compose
If you're using Docker Compose, you'll want to make sure that you're not calling our image directly with the image:
key. Instead, you'll want to use the build:
key and point to a Dockerfile
in your project.
Original docker-compose.yml file
services:
php:
image: serversideup/php:8.2.12-fpm-nginx-bookworm
volumes:
- .:/var/www/html/:cached
Updated docker-compose.yml
services:
php:
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/var/www/html/:cached
New File: Dockerfile
FROM serversideup/php:8.2.12-fpm-nginx-bookworm
# Switch to root so we can do root things
USER root
# Install the imagick extension with root permissions
RUN install-php-extensions imagick
# Drop back to our unprivileged user
USER www-data
Notice the services.php.build
options. We set a .
to look for a dockerfile called Dockerfile
within the same directory as our docker-compose.yml
file. If your project is large, you may also want to include .dockerignore
to ignore files that you do not want to include in your image.
For extra clarity, my project directory would look like this:
Project File Structure
.
├── Dockerfile
├── docker-compose.yml
└── public
└── index.php
The Dockerfile is where all the magic will happen. This is where we pull the Server Side Up image as a dependency, then run standard shell commands to add the extension that we need.
The next time you run docker compose up
, Docker will build and cache the image for you automatically.
You can verify the CLI option installed correctly by using php -i
in CLI or phpinfo()
in a PHP file.
⚠️ Important note about caching
- You'll notice Docker likes to cache image builds (which is great for most functions)
- If you make changes to your Dockerfile, you may need to include
--build
with your Docker compose command (read more here)
If you want to rebuild, then you would run this:
Rebuild on Docker Compose Initialization
docker compose up --build
Real-life example showing development to production
Here's an example showing a single Dockerfile with "multi-stage builds" so you can call certain targets as appropriate. This file is structured to centralize the PHP extension management in a single location.
Dockerfile
############################################
# Base Image
############################################
# Learn more about the Server Side Up PHP Docker Images at:
# https://serversideup.net/open-source/docker-php/
FROM serversideup/php:8.3-fpm-nginx AS base
# Switch to root before installing our PHP extensions
USER root
RUN install-php-extensions bcmath gd
############################################
# Development Image
############################################
FROM base AS development
# We can pass USER_ID and GROUP_ID as build arguments
# to ensure the www-data user has the same UID and GID
# as the user running Docker.
ARG USER_ID
ARG GROUP_ID
# Switch to root so we can set the user ID and group ID
USER root
RUN docker-php-serversideup-set-id www-data $USER_ID:$GROUP_ID && \
docker-php-serversideup-set-file-permissions --owner $USER_ID:$GROUP_ID --service nginx
# Switch back to the unprivileged www-data user
USER www-data
############################################
# CI image
############################################
FROM base AS ci
# Sometimes CI images need to run as root
# so we set the ROOT user and configure
# the PHP-FPM pool to run as www-data
USER root
RUN echo "user = www-data" >> /usr/local/etc/php-fpm.d/docker-php-serversideup-pool.conf && \
echo "group = www-data" >> /usr/local/etc/php-fpm.d/docker-php-serversideup-pool.conf
############################################
# Production Image
############################################
FROM base AS deploy
COPY --chown=www-data:www-data . /var/www/html
USER www-data
Common PHP extensions that you might need
We compiled a list of extensions for you to reference.
intl
intl is a PHP module that provides internationalization functions. You may want to install this module if you're using Laravel, specifically if you are validating emails with "DNS" or "spoof" validation.
Our tests showed this module will add about 40 MB of space to the Docker image, so we decided to not include it by default.
Learn more about the "intl" requirement for Laravel →
Don't see the extension you need?
If you're having trouble, open a discussion on GitHub →