petr_sys30 Jul 2025 07:42

Our PHP Docker image was 1.2 GB. After optimization it is 180 MB. Notes on what actually helped.

Multi-stage build removes dev tools from the final image:

FROM composer:2 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --prefer-dist --no-scripts --optimize-autoloader

FROM php:8.2-fpm-alpine AS runtime
RUN apk add --no-cache \
    libpq-dev \
    && docker-php-ext-install pdo_pgsql opcache

COPY --from=vendor /app/vendor /app/vendor
COPY . /app

Key points:

  • Alpine base saves 200+ MB vs Debian
  • --no-dev removes dev dependencies from vendor
  • Multi-stage keeps Composer out of the final image
  • Only install extensions you actually use
Replies (7)
alex_petrov30 Jul 2025 08:01

Alpine has some gotchas with glibc-dependent extensions. If you use extensions that link against glibc (some PECL extensions do), you need musl-compatible builds or switch to debian-slim which is still much smaller than the full image.

0
sergey_web30 Jul 2025 08:55

Add OPcache configuration in the Dockerfile: COPY opcache.ini /usr/local/etc/php/conf.d/. Do not rely on the .env file for OPcache settings because they need to be set before PHP starts.

0
petr_sys30 Jul 2025 10:48

The vendor copy order matters for layer caching. Copy composer files and run install BEFORE copying application code. That way code changes do not invalidate the vendor layer.

0
simondev30 Jul 2025 12:40

We use php:8.2-fpm-alpine as base and add a custom entrypoint script that runs php artisan migrate --force on start. Useful for deploy-on-start patterns. Just make sure the command is idempotent.

0
vova30 Jul 2025 14:24

docker scout or dive tool helps inspect layer sizes and find what is taking space. Often a single RUN step that leaves temp files in the layer is responsible for unexpected size.

0
petr_sys30 Jul 2025 16:20

One thing that bit us: composer dump-autoload --optimize needs to run AFTER all files are copied, not in the vendor stage. The classmap needs to know all app classes, not just vendor.

0
mdemir30 Jul 2025 16:44

For development, use a separate Dockerfile.dev that extends the runtime image and adds Xdebug, pcov, and dev dependencies. Never ship dev tooling in the production image.

0