После экстренного релиза PHP 21 октября 2026 года, закрывшего две критические уязвимости PHP2Shell (CVE-2026-109618 и CVE-2026-109619), владельцам сайтов на Docker нужно действовать иначе, чем при обновлении на обычном сервере. Здесь недостаточно поменять пакет — нужно пересобрать образ и передеплоить контейнеры. Разберём, как правильно обновить PHP в Docker-контейнерах, чтобы исправление действительно попало в работающий код, а не осталось только на бумаге.
Почему обновление PHP в Docker — это не просто docker pull
Когда PHP установлен на сервере напрямую, вы обновляете пакет и перезапускаете сервис. В Docker логика другая: PHP «запечён» внутрь образа. Если вы просто выполните docker compose pull, это обновит только те образы, которые явно указаны в конфигурации, но не пересоберёт ваш собственный образ приложения, если PHP в нём является частью сборки. Даже если на хосте уже есть свежий базовый образ, старый контейнер продолжит работать со старой версией PHP, пока вы не пересоберёте и не перезапустите его.
Поэтому главное правило: обновление PHP в Docker-контейнере — это изменение Dockerfile, пересборка образа и передеплой. Только так исправление гарантированно окажется внутри работающего приложения.
Шаг 1: Найдите, откуда в вашем образе берётся PHP
Прежде чем что-то менять, посмотрите на Dockerfile, который используется в продакшене. Если сборка многоступенчатая, проверяйте именно финальную стадию — ту, что попадает в рабочий контейнер. Обновление PHP на этапе сборки не гарантирует, что он обновится в финальном образе.
В большинстве случаев PHP приходит из официального образа, и строка выглядит примерно так:
FROM php:8.4-fpm-bookworm
Именно эту строку и нужно изменить. Не полагайтесь на плавающие теги вроде php:8.4-fpm: хотя официальные образы обычно обновляются в день релиза, некоторые ветки могут отставать. Например, тег php:8.2-fpm ещё может указывать на старую версию, поэтому для PHP 8.2 лучше явно закрепить php:8.2.35-fpm.
Шаг 2: Обновите версию в Dockerfile
Исправленные версии, которые нужно указать: PHP 8.5.12, 8.4.27, 8.3.36 или 8.2.35 — в зависимости от вашей ветки. Замените тег в строке FROM на нужный. Например, для PHP 8.4 с FPM:
# было
FROM php:8.4-fpm-bookworm
# стало
FROM php:8.4.27-fpm-bookworm
Если вы используете ARG для версии PHP, обновите значение аргумента. Такой подход удобен, когда версия фигурирует в нескольких местах Dockerfile или в docker-compose.
Для дополнительной защиты можно закрепить не только тег, но и digest образа — неизменяемый идентификатор, который гарантирует, что вы соберёте именно ту версию, которую проверили. Получить digest можно командой docker buildx imagetools inspect php:8.4.27-fpm --format '{{.Manifest.Digest}}', а затем указать его в FROM через @sha256:.... Это не обязательно, но полезно для продакшена, где важна воспроизводимость сборки.
Шаг 3: Пересоберите и передеплойте
После изменения Dockerfile образ нужно пересобрать без кэша, чтобы гарантированно подтянуть новый базовый слой. Если вы используете Docker Compose, команды выглядят так:
docker compose build --pull --no-cache
docker compose up -d --force-recreate
Флаг --pull заставляет Docker проверить наличие более свежего базового образа, а --no-cache исключает использование старых слоёв. --force-recreate гарантирует, что контейнеры будут пересозданы, а не просто перезапущены — иначе старый процесс PHP может продолжить работать.
Если вы используете оркестратор вроде Kubernetes, обновите образ в манифесте и выполните rollout. Ключевой момент тот же: новые поды должны быть созданы на основе пересобранного образа, а не просто перезапущены.
Шаг 4: Убедитесь, что версия действительно обновилась
Самая распространённая ошибка — предположить, что пересборка сработала, и не проверить результат. Обязательно загляните внутрь работающего контейнера и посмотрите версию PHP:
docker compose exec php -v
Команда должна показать исправленную версию, например PHP 8.4.27. Если в образе нет CLI, используйте php-fpm -v или проверьте версию через docker scout sbom. Не доверяйте тегу на бумаге — доверяйте выводу команды внутри контейнера.
После проверки пройдитесь по основным сценариям сайта: формы, корзина, вход в админку. Смена версии PHP иногда выявляет несовместимости с устаревшими расширениями или плагинами, и лучше поймать их сразу.
Что делать, если вы на старой ветке PHP
Если в Dockerfile указан PHP 8.1 или более старая версия, официальных обновлений для неё уже нет. Для 7.4, 8.0 и 8.1 существуют только исходные бэкпорты, которые нужно собирать самостоятельно, либо можно поискать готовые образы от сообщества. Но надёжнее — перейти на поддерживаемую ветку: 8.2 (до конца 2026 года), 8.3, 8.4 или 8.5. Это потребует проверки совместимости приложения, но оставлять сайт на версии без патчей безопасности — риск, который в случае с PHP2Shell слишком велик.
Если вы не уверены, какая версия PHP используется в ваших контейнерах и как правильно пересобрать образ без простоя, напишите нам — поможем проверить конфигурацию и обновить PHP в Docker так, чтобы исправление действительно защитило сайт.
