Текуща ситуация: PHP2Shell. Две критични уязвимости в PHP (CVSS 9,2) позволяват злонамерен код без вход. Корекции от 21.10.2026 г.Какво да направите сега →

Експлоатация на PHP в контейнери

PHP в контейнер изисква подходящ вариант на образа, конфигурация за продукция, разумни граници на паметта и процес, който изгражда образите наново при всяко издание за сигурност.

Актуалност 5 мин. четенеЗнания за PHP

Накратко: За да работите с PHP в контейнери, изберете подходящия вариант на официалния образ (fpm, apache или cli), активирайте php.ini за продукция, инсталирайте само нужните разширения и задайте граници за паметта и процесите, които си пасват. Контейнерите са неизменяеми: актуализация за сигурност на PHP като тази за PHP2Shell действа едва когато образът е изграден наново и всеки контейнер е рестартиран. Това ново изграждане затова принадлежи като твърд процес във всяка експлоатация на контейнери.

Защо PHP в контейнери?

Контейнерите опаковат PHP, разширенията и конфигурацията в образ, който работи еднакво на всеки сървър. За фирмите това означава: по-малко изненади между тест и продукция, по-бързо възстановяване и ясни версии. За сигурността това обаче означава и ново задължение: в контейнер никой не внедрява актуализации автоматично.

Тази страница разглежда текущата експлоатация. Как конкретно да пачнете съществуващи контейнери срещу PHP2Shell, е описано в Пачване на PHP в Docker контейнери.

Избор на правилния вариант на образа

Вариант Съдържание Типично приложение
php:<version>-fpm PHP-FPM, изисква предварително включен уеб сървър продукция с Nginx, Caddy или Ingress
php:<version>-apache Apache с mod_php, по подразбиране mpm_prefork прости конструкции, по-стари приложения
php:<version>-cli команден ред, единственият вариант, който съдържа и php-cgi cron задачи, worker процеси на опашки, стъпки на изграждане
…-alpine върху Alpine Linux с musl малки образи, при някои разширения са нужни адаптации
…-bookworm, …-trixie върху посочената версия на Debian твърда основа за възпроизводими билдове

За нови проекти по правило се препоръчва вариантът fpm с отделен контейнер за уеб сървъра. При mod_php екипът на PHP във връзка с PHP2Shell вижда най-високия риск; който използва образа apache, експлоатира точно този режим на работа.

Изграждане на образ за продукция

Компактен пример за приложение с достъп до MySQL:

FROM php:8.4-fpm-alpine

# Активиране на конфигурацията за продукция (според документацията на образа настоятелно препоръчано)
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"

# Само нужните разширения
RUN docker-php-ext-install -j"$(nproc)" pdo_mysql

# Собствени настройки
COPY zz-sicherheit.ini "$PHP_INI_DIR/conf.d/"

# Кодът принадлежи на root; FPM worker процесите работят като www-data и могат само да го четат
COPY . /var/www/html

Помощните скриптове на образа поемат изграждането на разширения: docker-php-ext-configure за опции, docker-php-ext-install за изграждане, docker-php-ext-enable за активиране, например след pecl install. Ако с docker-php-source се разархивира изходният код, според документацията той трябва да се изтрие отново в същия слой. Файлът zz-sicherheit.ini може да изглежда така:

expose_php = Off
display_errors = Off
log_errors = On
session.use_strict_mode = 1
session.cookie_httponly = 1

Два допълнителни принципа правят образите по-устойчиви. Първо, доставеният образ съдържа само онова, което е нужно по време на изпълнение; компилаторите, кешовете на пакети и тестовите файлове принадлежат в отделна стъпка на изграждане. Второ, потребителят, под който работи PHP, трябва да може да пише само там, където е необходимо, например в директории за качване или кеш върху прикачени томове. Много екипи допълнително работят с контейнера със защитена от запис файлова система. Внедрен PHP файл тогава много по-трудно остава трайно, а всяко рестартиране възстановява чистото състояние на образа. Това не замества изследване след инцидент, но осезаемо намалява повърхността за атака.

Процеси, памет и логове в контейнера

Три регулатора определят дали един PHP контейнер работи стабилно.

  1. Брой worker процеси: pm.max_children в FPM пула определя колко заявки се обработват едновременно. Всеки worker може да заеме до memory_limit.
  2. Граница на паметта на контейнера: Тя ограничава всички процеси заедно. Като груба рецепта важи: броят на worker процесите по паметта на worker плюс резерв трябва да се побира под границата, иначе системата прекратява процеси.
  3. Логове: Контейнерите записват логове в стандартния изход. В PHP-FPM catch_workers_output = yes пренасочва изхода на worker процесите към основния лог; без тази настройка според ръководството той се губи.

Полезен е и request_terminate_timeout, който прекратява отделни заявки след определен период, когато max_execution_time не действа. Как се работи с контейнери в клъстер, описва Пачване на PHP в Kubernetes.

Контейнери и сигурност: какво показа PHP2Shell

При PHP2Shell контейнерите играят двойна роля. От една страна са помощ: php.net препоръчва като временна мярка за CVE-2026-109618 memory_limit=-1 да се комбинира с граница на паметта чрез контейнер или cgroup, в идеалния случай така, че да се прекратява само засегнатият worker. RLIMIT_AS и RLIMIT_DATA според php.net са неподходящи за целта. Тази мярка не е пълна защита и не замества актуализацията.

От друга страна контейнерите са капан, ако образите не се изграждат наново. Образ с PHP 8.4.26 остава уязвим, колкото и често да се рестартира контейнерът. Едва ново изграждане на 8.4.27 или по-нова и подмяната на всички работещи контейнери затварят уязвимостта. Състоянието може да се провери директно в работещия контейнер:

docker exec <container> php -v
docker exec <container> php-fpm -v
docker exec <container> php -r 'var_dump(ini_get("memory_hard_limit_percent"));'

Ако последната команда върне bool(false), PHP не познава директивата, въведена с коригираните версии; според ръководството версията тогава е засегната. Трайно помага само автоматично ново изграждане, както е описано в CI/CD: автоматично ново изграждане на образите на PHP.

Съвет

Задайте в Dockerfile точната версия на PHP в тага и я повишавайте съзнателно. Така в кода е проследимо кога коя версия е внедрена.

Как помага PHP SOS конкретно?

В заздравяването на сървъра за PHP уеб сървъри се грижим и за контейнерите:

  • Проверка на образите: Базов образ, версия на PHP, разширения и конфигурация на всеки образ.
  • Заздравяване на конфигурацията: ini за продукция, компактен списък с разширения, подходящи граници на worker процесите и паметта.
  • Настройване на новото изграждане: Процес, който изгражда наново и внедрява образите при нови издания на PHP.
  • Контрол на средата за изпълнение: Доказваме, че във всеки работещ контейнер работи коригираната версия.

Често задавани въпроси

Кой вариант на образа на PHP е правилният?

За Nginx или друго прокси – вариантът fpm, за прост строеж с Apache – вариантът apache, за скриптове и cron задачи – вариантът cli. Вариантите с Alpine са по-малки, но се основават на musl вместо glibc, което проличава при някои разширения.

PHP в контейнер актуализира ли се автоматично?

Не. Работещият контейнер не се променя. Трябва да изградите наново образа с новата версия на PHP и да рестартирате контейнерите. Едва тогава работи коригираната версия.

Как се свързват memory_limit и границата на контейнера?

memory_limit ограничава всяка отделна PHP заявка, а границата на контейнера – целия контейнер. И двете трябва да си пасват: броят на worker процесите по паметта на worker трябва да е под границата на контейнера.

Нужен ли ми е php.ini в контейнерите?

Да. Официалните образи носят php.ini-development и php.ini-production като шаблони. За продукция документацията на образа изрично препоръчва шаблона за продукция; собствените настройки отиват в conf.d.

Източници

Незабавен контакт

Всеки час има значение. Пишете ни сега.

Опишете накратко системата, версията на PHP и какво сте забелязали. Ние се свързваме с Вас, уточняваме ситуацията и работим отдалечено, докато инцидентът бъде приключен и документиран.

Незабавна помощ