Контейнеризация PHP 8.4 при помощи Docker. Подробное руководство

Раздел: DevOps -> Docker образы PHP

Основные подходы к созданию Docker образа с PHP 8.4

Как получить минимальный и эффективный образ для PHP 8.4?

Оптимальным решением является использование официального образа php:8.4-fpm-alpine. Этот образ базируется на Alpine Linux, что даёт малый размер (около 50 МБ) и высокую безопасность. Ниже приведён Dockerfile с установкой нескольких популярных расширений.

FROM php:8.4-fpm-alpine

RUN apk add --no-cache \
    libzip-dev \
    libpng-dev \
    libjpeg-turbo-dev \
    freetype-dev \
    oniguruma-dev \
    libxml2-dev \
    postgresql-dev \
    && docker-php-ext-install \
        pdo_mysql \
        pdo_pgsql \
        mbstring \
        exif \
        pcntl \
        bcmath \
        gd \
        zip \
        intl \
        opcache \
    && pecl install redis \
    && docker-php-ext-enable redis \
    && apk del --purge \
        libzip-dev \
        libpng-dev \
        libjpeg-turbo-dev \
        freetype-dev \
        oniguruma-dev \
        libxml2-dev \
        postgresql-dev \
    && rm -rf /var/cache/apk/*

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html

USER www-data

EXPOSE 9000

CMD ["php-fpm"]

Docker php 8.4 (образ docker с php 8.4)

Пояснение: apk add --no-cache устанавливает зависимости для сборки расширений, docker-php-ext-install компилирует и включает расширения, pecl install redis добавляет Redis, а COPY --from=composer копирует Composer из отдельного образа. Финальная очистка удаляет лишние пакеты.

Типичные проблемы и их решения:

  • Ошибка configure: error: Package requirements (libcurl >= 7.29.0) were not met - не хватает curl-dev. Добавьте в apk add curl-dev.
  • Проблема с правами доступа при записи в volume - в образе используется пользователь www-data. Убедитесь, что хостовые папки имеют соответствующие права (например, chown -R 82:82 .).
  • Ошибка Fatal error: Uncaught Error: Call to undefined function bcdiv() - расширение bcmath не включено. Добавьте его в список docker-php-ext-install.

Вариант 1. Как построить образ на основе Debian (php:8.4-fpm) для совместимости с устаревшими расширениями?

В случаях, когда Alpine не поддерживает некоторые библиотеки (например, imap или mssql), лучше взять Debian-версию образа. Размер будет больше (~200 MB), но совместимость выше.

FROM php:8.4-fpm

RUN apt-get update && apt-get install -y \
        libzip-dev \
        libpng-dev \
        libjpeg62-turbo-dev \
        libfreetype6-dev \
        libonig-dev \
        libxml2-dev \
        libpq-dev \
        libcurl4-openssl-dev \
        libssl-dev \
        unzip \
    && docker-php-ext-install \
        pdo_mysql \
        pdo_pgsql \
        mbstring \
        exif \
        pcntl \
        bcmath \
        gd \
        zip \
        intl \
        opcache \
    && pecl install xdebug \
    && docker-php-ext-enable xdebug \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

Проблема:

При установке расширения gd часто возникает конфликт версий libpng. Решение - явно указать флаги конфигурации: --with-freetype --with-jpeg. Добавьте перед docker-php-ext-configure gd --with-freetype --with-jpeg.

Вариант 2. Как совместить PHP-FPM и Nginx в одном контейнере?

Для разработки удобно иметь единый контейнер с двумя процессами. Используется супервизор (supervisor) для запуска обоих сервисов.

FROM php:8.4-fpm-alpine

RUN apk add --no-cache nginx supervisor \
    && docker-php-ext-install opcache \
    && mkdir -p /run/nginx

COPY docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY docker/nginx.conf /etc/nginx/nginx.conf
COPY docker/php.ini /usr/local/etc/php/conf.d/custom.ini

WORKDIR /var/www/html
EXPOSE 80 9000

CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

Проблема:

Nginx может не дождаться запуска PHP-FPM, что вызовет ошибку 502. В конфигурации супервизора нужно использовать autorestart=true и задать startsecs=0 для fpm.

Вариант 3. Как использовать многостадийную сборку для уменьшения финального образа?

Сборка расширений в первом образе с dev-зависимостями, затем копирование артефактов в чистый минимальный образ.

FROM php:8.4-fpm-alpine AS builder

RUN apk add --no-cache autoconf build-base linux-headers libzip-dev \
    && docker-php-ext-install zip

FROM php:8.4-fpm-alpine

COPY --from=builder /usr/local/lib/php/extensions /usr/local/lib/php/extensions
RUN docker-php-ext-enable zip

# далее установка приложения...

Проблема:

Зависимости расширений (.so файлы) могут требовать дополнительные библиотеки (например, libzip.so). Финальный образ также должен содержать runtime-зависимости. Добавьте apk add --no-cache libzip во второй образ.

Расширенные примеры использования Docker с PHP 8.4

Пример 1. Полный Dockerfile с предустановленным Xdebug и настройкой окружения

Пример
FROM php:8.4-fpm-alpine

RUN apk add --no-cache $PHPIZE_DEPS \
    && pecl install xdebug-3.4.0 \
    && docker-php-ext-enable xdebug \
    && apk del $PHPIZE_DEPS

COPY xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini

ENV XDEBUG_MODE=debug
ENV XDEBUG_CLIENT_HOST=host.docker.internal

CMD ["php-fpm"]
После сборки (docker build -t php84-xdebug .) и запуска контейнера, Xdebug будет активен. Проверка: php -v должен показать версию с Xdebug.

Пример 2. Docker Compose с PHP 8.4, Nginx, PostgreSQL и Redis

Пример
version: '3.8'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./src:/var/www/html
    expose:
      - 9000
    networks:
      - app-net
  nginx:
    image: nginx:alpine
    volumes:
      - ./src:/var/www/html
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    ports:
      - "8080:80"
    networks:
      - app-net
    depends_on:
      - app
  db:
    image: postgres:17-alpine
    environment:
      POSTGRES_DB: testdb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    networks:
      - app-net
  redis:
    image: redis:7-alpine
    networks:
      - app-net

networks:
  app-net:
Запуск: docker compose up -d. Приложение доступно на http://localhost:8080.

Пример 3. Установка дополнительных PHP расширений через PECL в Alpine

Пример
FROM php:8.4-fpm-alpine

RUN apk add --no-cache \
        $PHPIZE_DEPS \
        libzmq zeromq-dev \
        librabbitmq-c-dev \
    && pecl install zmq-1.1.3 \
    && pecl install amqp-2.0.0 \
    && docker-php-ext-enable zmq amqp \
    && apk del $PHPIZE_DEPS \
    && rm -rf /tmp/pear/
После сборки расширения zmq и amqp будут доступны. Проверка: php -m | grep -E 'zmq|amqp'.

Пример 4. Многостадийная сборка с Composer и оптимизацией автозагрузчика

Пример
FROM composer:latest AS composer
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader

FROM php:8.4-fpm-alpine
COPY --from=composer /app/vendor /var/www/vendor
COPY src/ /var/www/html
RUN docker-php-ext-install opcache pdo_mysql

USER www-data
Сборка: docker build -t php84-app . . Результат - образ без зависимостей для разработки, с оптимизированным автозагрузчиком.

Пример 5. Настройка часового пояса и локали в Debian-образе

Пример
FROM php:8.4-fpm

RUN apt-get update && apt-get install -y locales \
    && echo "ru_RU.UTF-8 UTF-8" >> /etc/locale.gen \
    && locale-gen ru_RU.UTF-8 \
    && ln -sf /usr/share/zoneinfo/Europe/Moscow /etc/localtime \
    && dpkg-reconfigure -f noninteractive tzdata \
    && apt-get clean
После сборки контейнер будет использовать московское время и русскую локаль. Проверка: date в контейнере покажет правильное время.

образ Docker с PHP 8.4 - comments

En
Docker php 8.4 (php)