Below is an example Dockerfile
that we recommend at Depot for building images for PHP applications with Composer.
# syntax=docker/dockerfile:1
FROM php:8.4-fpm
RUN apt-get update && apt-get install -y --no-install-recommends \
libzip-dev \
nginx \
supervisor \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=composer/composer:2.8-bin /composer /usr/bin/composer
COPY composer.json ./
RUN --mount=type=cache,target=/root/.composer/cache \
composer install \
--no-dev \
--no-interaction \
--no-progress \
--optimize-autoloader \
--apcu-autoloader
RUN apt-get update && apt-get install -y --no-install-recommends $PHPIZE_DEPS && \
docker-php-ext-install -j$(nproc) \
opcache \
zip && \
apt-get remove --purge -y $PHPIZE_DEPS && \
apt-get autoremove -y && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
COPY php-production.ini /usr/local/etc/php/conf.d/99-production.ini
COPY nginx.conf /etc/nginx/http.d/default.conf
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY public ./public
ENTRYPOINT ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
This Dockerfile uses a streamlined single-stage build approach for a PHP application with Composer:
FROM php:8.4-fpm
RUN apt-get update && apt-get install -y --no-install-recommends \
libzip-dev \
nginx \
supervisor \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
We start with PHP 8.4 FPM for a reliable base image. We install the essential packages:
libzip-dev
for ZIP file handlingnginx
for web serversupervisor
for process managementCOPY --from=composer/composer:2.8-bin /composer /usr/bin/composer
COPY composer.json ./
RUN --mount=type=cache,target=/root/.composer/cache \
composer install \
--no-dev \
--no-interaction \
--no-progress \
--optimize-autoloader \
--apcu-autoloader
Instead of using a separate composer stage, we copy the composer binary directly from the official composer image. We then copy the composer.json
file and install dependencies with cache mounting for faster subsequent builds. The installation uses production-optimized flags.
RUN apt-get update && apt-get install -y --no-install-recommends $PHPIZE_DEPS && \
docker-php-ext-install -j$(nproc) \
opcache \
zip && \
apt-get remove --purge -y $PHPIZE_DEPS && \
apt-get autoremove -y && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
We install PHP extensions efficiently by installing build dependencies, compiling extensions, and then removing build dependencies in a single RUN command to minimize image layers and size:
opcache
for bytecode cachingzip
for ZIP file operationsCOPY php-production.ini /usr/local/etc/php/conf.d/99-production.ini
COPY nginx.conf /etc/nginx/http.d/default.conf
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY public ./public
ENTRYPOINT ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
We copy the necessary configuration files for PHP, Nginx, and Supervisor, then copy only the public directory of our application. The container uses Supervisor to manage both PHP-FPM and Nginx processes.
Cache mounts are one of the most powerful features for optimizing Docker builds with Depot. This Dockerfile uses the following cache mount syntax:
RUN --mount=type=cache,target=/root/.composer/cache \
composer install \
--no-dev \
--no-interaction \
--no-progress \
--optimize-autoloader \
--apcu-autoloader
type=cache
: Specifies this is a cache mount. The cache persists across builds and is managed by BuildKit (and Depot's distributed cache system).target=/root/.composer/cache
: The mount point inside the container where the cache is accessible. This matches Composer's default cache directory.For more information regarding Composer cache mounts, please visit the official Composer documentation.