---
head.title: 'Installing additional PHP extensions - Docker PHP - Server Side Up'
description: 'Learn how to add any PHP extension that you need for your application.'
layout: docs
---

# 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`](https://github.com/mlocati/docker-php-extension-installer) 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](https://github.com/mlocati/docker-php-extension-installer#supported-php-extensions). Once you have the name of the extensions, you'll need to add it to the `Dockerfile` in your project.

::note
**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.
::

::code-panel
---
label: "Example: Installing the \"intl\" extension"
---
```dockerfile
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 →](https://github.com/mlocati/docker-php-extension-installer)

## 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.

::code-panel
---
label: Original docker-compose.yml file
---
```yaml
services:
  php:
    image: serversideup/php:8.2.12-fpm-nginx-bookworm
    volumes:
      - .:/var/www/html/:cached
```
::

::code-panel
---
label: "Updated docker-compose.yml"
---
```yaml
services:
  php:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/var/www/html/:cached
```
::

::code-panel
---
label: "New File: Dockerfile"
---
```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`](https://docs.docker.com/engine/reference/builder/#dockerignore-file) to ignore files that you do not want to include in your image.

For extra clarity, my project directory would look like this:

::code-panel
---
label: Project File Structure
---
```txt
.
├── 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](https://docs.docker.com/compose/reference/up/))

If you want to rebuild, then you would run this:
::code-panel
---
label: Rebuild on Docker Compose Initialization
---
```sh
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.

::code-panel
---
label: Dockerfile
---
```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](https://www.php.net/manual/en/intro.intl.php) 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 →](https://laravel.com/docs/10.x/validation#rule-email)

### Don't see the extension you need?
If you're having trouble, [open a discussion on GitHub →](https://github.com/serversideup/docker-php/discussions/new?category=q-a)
