Base Image
FROM php:8.3-fpm-alpine
Alpine Linux keeps the image small. Use -fpm for web applications behind Nginx.
Installing Extensions
# System dependencies for common PHP extensions
RUN apk add --no-cache \
libpng-dev \
libzip-dev \
icu-dev \
postgresql-dev \
oniguruma-dev
# Install PHP extensions
RUN docker-php-ext-install \
pdo_mysql \
pdo_pgsql \
mbstring \
zip \
gd \
intl \
opcache \
bcmath
Composer Dependencies
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Install dependencies (cache-friendly layer ordering)
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader --no-scripts
# Then copy application code
COPY . .
RUN composer dump-autoload --optimize
OPcache Configuration
# /usr/local/etc/php/conf.d/opcache.ini
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.validate_timestamps=0
opcache.interned_strings_buffer=16
opcache.jit=tracing
opcache.jit_buffer_size=64M
Tip Set
validate_timestamps=0in production — it tells OPcache to never check if files changed, which is safe in containers where code is immutable.
Complete Production Dockerfile
FROM php:8.3-fpm-alpine AS base
# System deps
RUN apk add --no-cache libpng libzip icu postgresql-libs oniguruma
FROM base AS build
RUN apk add --no-cache libpng-dev libzip-dev icu-dev postgresql-dev oniguruma-dev
RUN docker-php-ext-install pdo_mysql pdo_pgsql mbstring zip gd intl opcache bcmath
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader --no-scripts
COPY . .
RUN composer dump-autoload --optimize
FROM base
COPY --from=build /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/
COPY --from=build /usr/local/etc/php/conf.d/ /usr/local/etc/php/conf.d/
COPY --from=build /var/www /var/www
COPY docker/php/opcache.ini /usr/local/etc/php/conf.d/
COPY docker/php/php.ini /usr/local/etc/php/conf.d/
RUN adduser -D -u 1000 app
USER app
WORKDIR /var/www
EXPOSE 9000
CMD ["php-fpm"]
Nginx Companion
server {
listen 80;
root /var/www/public;
index index.php;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
| Image Size | Configuration |
|---|---|
| ~450 MB | php:8.3-fpm (Debian) |
| ~120 MB | php:8.3-fpm-alpine |
| ~80 MB | Multi-stage with alpine |