Контейнеризация PHP-приложения
Напишите готовый к эксплуатации PHP Dockerfile
«Контейнеризация PHP-приложения» — бесплатный урок PHP Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения PHP Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс PHP Academy содержит 4 уроков всего.
Зачем контейнеризировать PHP
Предсказуемая поставка PHP означает фиксацию точной версии интерпретатора, расширений и библиотек ОС вместе с кодом. Образ Docker предоставляет каждой среде — ноутбуку, среде непрерывной интеграции и рабочей среде — одинаковый результат php -v и одинаковый набор ext-*.
В этом уроке мы создадим образ, готовый к эксплуатации: PHP-FPM, только нужные расширения, настроенные конфигурации, пользователя без прав суперпользователя и проверку работоспособности.
FPM или базовый образ Apache
Официальные образы PHP выпускаются в разных вариантах. Для рабочего веб-приложения за nginx или traefik выбирайте php:8.3-fpm-alpine (компактный) или php:8.3-fpm (Debian, glibc — меньше неожиданностей с нативными библиотеками).
cli— рабочие процессы, очереди, планировщик заданийfpm— менеджер процессов FastCGI, работает в паре с nginxapache— встроенный Apache, удобно, но тяжелее
Зафиксируйте минорную версию. Никогда не используйте :latest в рабочей среде.
# Base image choice in your Dockerfile
FROM php:8.3-fpm-alpine AS base
# Why alpine? ~30MB base vs ~140MB Debian.
# Tradeoff: musl libc, occasional native-extension friction.Установка расширений
Никогда не выполняйте apt install php-xxx внутри этих образов — используйте встроенные вспомогательные средства docker-php-ext-install, docker-php-ext-configure и pecl. Скрипт install-php-extensions от mlocati — фактический стандартный способ, который сам загружает нужные заголовочные файлы для разработки.
FROM php:8.3-fpm-alpine
# Grab the helper that resolves build deps automatically
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions && \
install-php-extensions \
pdo_mysql \
opcache \
intl \
zip \
redis \
bcmathComposer в образе
Копируйте исполняемый файл Composer из его официального образа, а не загружайте установщик напрямую. Для рабочей среды запускайте composer install с параметрами --no-dev и --optimize-autoloader, а сначала копируйте только composer.json и composer.lock, чтобы слой зависимостей кэшировался независимо от изменений исходного кода.
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /app
# Cache-friendly: deps layer invalidates only when lock changes
COPY composer.json composer.lock ./
RUN composer install \
--no-dev \
--no-scripts \
--no-autoloader \
--prefer-dist
COPY . .
RUN composer dump-autoload --optimize --classmap-authoritativeНастройка php.ini
Базовый образ содержит шаблоны php.ini-production и php.ini-development. Активируйте производственный вариант, затем добавьте собственные переопределения в conf.d: этот каталог объединяется последним, поэтому его значения имеют приоритет.
Основные значения для рабочей среды: opcache.enable=1, opcache.validate_timestamps=0 (неизменяемый код в образе) и разумное ограничение memory_limit.
# Activate production ini
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
# Custom overrides win because conf.d loads last
COPY docker/php/zz-app.ini $PHP_INI_DIR/conf.d/zz-app.iniФайл переопределения OPcache
Это самое значительное улучшение для рабочей среды. При значении validate_timestamps=0 PHP не проверяет метаданные файлов при каждом запросе, но это означает, что вы MUST пересобирать образ для развёртывания изменений — именно этого мы и хотим от неизменяемых контейнеров.
; docker/php/zz-app.ini
memory_limit = 256M
expose_php = Off
opcache.enable = 1
opcache.enable_cli = 0
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 0
opcache.preload = /app/preload.php
opcache.preload_user = www-dataЗапуск без прав суперпользователя
В образе уже определён пользователь www-data. Запуск FPM от имени суперпользователя без необходимости увеличивает поверхность атаки. Назначьте владельца для доступных на запись путей (кэша и журналов) и переключите пользователя с помощью USER перед CMD.
Главный процесс FPM всё ещё привязывается к привилегированным портам? Нет — FPM прослушивает порт 9000 (непривилегированный), поэтому запуск без прав суперпользователя прост.
# Make runtime-writable dirs owned by the runtime user
RUN chown -R www-data:www-data /app/var /app/storage 2>/dev/null || true
USER www-data
EXPOSE 9000
CMD ["php-fpm"]Проверки работоспособности
Оркестраторам нужен сигнал о том, что FPM действительно работает, а не просто что процесс существует. cgi-fcgi может отправить запрос конечной точке FPM /status или /ping. Сначала включите pm.status_path и ping.path в пуле FPM.
# In www.conf pool config:
; ping.path = /ping
; ping.response = pong
# Dockerfile HEALTHCHECK using cgi-fcgi
RUN install-php-extensions @composer >/dev/null 2>&1 || true
HEALTHCHECK --interval=10s --timeout=3s --retries=3 \
CMD SCRIPT_NAME=/ping SCRIPT_FILENAME=/ping REQUEST_METHOD=GET \
cgi-fcgi -bind -connect 127.0.0.1:9000 || exit 1Составление Dockerfile
Вот цельный рабочий Dockerfile с одним этапом. На следующем уроке мы разделим его на несколько этапов, чтобы исключить инструменты сборки. Обратите внимание на порядок: зависимости → конфигурация → исходный код → автозагрузчик → смена пользователя.
FROM php:8.3-fpm-alpine
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions && \
install-php-extensions pdo_mysql opcache intl zip redis
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /app
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY docker/php/zz-app.ini $PHP_INI_DIR/conf.d/
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist
COPY . .
RUN composer dump-autoload --optimize --classmap-authoritative && \
chown -R www-data:www-data /app/var
USER www-data
EXPOSE 9000
CMD ["php-fpm"]Проверка сборки
После сборки проверьте, что действительно попало в образ: версию PHP, загруженные расширения и отключённую проверку OPcache. Небольшой сценарий для CLI подтверждает контракт среды выполнения, от которого зависит ваше приложение.
<?php
// Run inside the container: php verify.php
echo 'PHP ' . PHP_VERSION . PHP_EOL;
$required = ['pdo_mysql', 'opcache', 'intl', 'zip'];
foreach ($required as $ext) {
printf("%-12s %s\n", $ext, extension_loaded($ext) ? 'OK' : 'MISSING');
}
var_dump((bool) ini_get('opcache.enable'));
?>Гигиена контекста сборки
.dockerignore уменьшает контекст сборки и не позволяет секретам и разросшимся зависимостям из vendor попасть в образ и нарушить кэширование. Исключите vendor, VCS, файлы env и локальные инструменты.
# .dockerignore
.git
.gitignore
vendor/
node_modules/
.env
.env.*
tests/
*.md
docker-compose*.yml
storage/logs/*
var/cache/*Быстрая проверка
Зачем устанавливать opcache.validate_timestamps=0 в рабочем образе?
Итоги
Вы создали рабочий образ PHP-FPM: закрепили базовый образ 8.3-fpm-alpine, установили только необходимые расширения с помощью сценария установки, скопировали Composer и кэшированные зависимости в отдельный слой, активировали рабочий php.ini с переопределением настроек OPcache, переключились на www-data и добавили проверку работоспособности FPM.
Главные привычки: закрепляйте версии, кэшируйте слой зависимостей, запускайте процессы от имени непривилегированного пользователя, отключайте проверку временных меток и уменьшайте контекст сборки с помощью .dockerignore.
Изучай PHP с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 49
- Уроки
- 195
Часто задаваемые вопросы
Урок «Контейнеризация PHP-приложения» бесплатный?
Да — полный текст урока «Контейнеризация PHP-приложения» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс PHP Academy, подпишись на CoddyKit PRO. Курс PHP Academy содержит 4 уроков всего.
Чему я научусь в уроке «Контейнеризация PHP-приложения»?
Напишите готовый к эксплуатации PHP Dockerfile Ты практикуешь PHP Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать PHP Academy?
Предыдущий опыт не требуется. PHP Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Контейнеризация PHP-приложения»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке PHP Academy?
Да. Каждый урок PHP Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Контейнеризация PHP-приложения
- Многоэтапная сборка и оптимизация
- Docker Compose для локальных стеков
- CI/CD с GitHub Actions