Customizing The Docker Image

This guide will walk you through how to customize your Docker image for your project. You can add additional packages, change the PHP version, or even add additional services to your Docker image.

Where your Docker image is defined

You'll notice two files in your project that are used for your application:

Project Dockerfiles

.
├── Dockerfile.node # Used for Node
└── Dockerfile.php # Used for PHP

Customizing the image

You'll notice in the files are a FROM statement. These are the base images that we use for your project. You can visit each of the Docker Hub pages for that image to see full examples of how to customize the image.

We also utilize multi-stage builds with Docker so we can customize experiences based on the environment.

For the PHP image, we use our own open-source image called serversideup/php, which are highly optimized for Spin and Laravel projects.

Installing PHP extensions

The serversideup/php project comes with a lot of great documentation, specifically on how to install additional PHP extensions.

Here's an example of installing bcmath and gd PHP extensions:

Dockerfile.php

############################################
# 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-alpine AS base

# Since the container is unprivileged by default, we need to switch to root
# to install additional 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

# Set the user ID and group ID for www-data
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

# Drop privileges back to www-data    
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

Understanding targets

In the docker-compose.dev.yml file, you'll notice that we use the target argument to specify which stage of the Dockerfile to use. This will only build the image for that specific stage.

docker-compose.dev.yml

services:
  php:
    build:
      target: development
      args:
        USER_ID: ${SPIN_USER_ID}
        GROUP_ID: ${SPIN_GROUP_ID}
      dockerfile: Dockerfile.php

The above will look for Dockerfile.php and build the development stage of the Dockerfile, while passing some environment variables to the development build stage to ensure our file permissions are correct.