Коротко
Оновлення пакетів на хост-системі не зачіпає PHP усередині контейнера. Потрібно взяти свіжий базовий образ, зібрати свій заново та перезапустити контейнери. Перевіряти версію слід усередині контейнера, а не на хості.
Крок 1. Зрозуміти, що у вас усередині
docker ps --format '{{.Names}}\t{{.Image}}'
docker exec -it назва_контейнера php -v
docker exec -it назва_контейнера sh -c 'dpkg -l | grep php || rpm -q php-cli'Офіційні образи PHP зібрано з вихідного коду, тому номер версії там чесний: 8.3.36 і новіша — виправлено, 8.3.35 і старіша — ні.
Крок 2. Оновити базовий образ
Якщо в Dockerfile закріплено точний тег, підніміть його до виправленої версії:
FROM php:8.3.36-fpm-bookwormЯкщо тег плаваючий (php:8.3-fpm), достатньо завантажити образ заново:
docker pull php:8.3-fpm
docker compose build --pull --no-cache
docker compose up -dПрапорець --pull тут ключовий: без нього збірка візьме старий шар із локального кешу, і вразливість залишиться.
Крок 3. Перевірити результат
docker compose exec php php -v
docker compose exec php php -r 'echo PHP_VERSION, PHP_EOL;'Версія має бути не нижчою за 8.3.36 для гілки 8.3, 8.4.27 для 8.4, 8.5.12 для 8.5, 8.2.35 для 8.2.
Крок 4. Переконатися, що старі контейнери не працюють
Часта помилка: образ оновлено, а поруч працює контейнер, запущений тиждень тому.
docker ps --format '{{.Names}}\t{{.Image}}\t{{.CreatedAt}}'Якщо контейнер створено раніше, ніж ви перезібрали образ, створіть його заново.
Щоб не повторилося
- Закріплюйте точні теги версій — так видно, що саме розгорнуто.
- Перезбирайте образи за розкладом, а не лише під час правки коду: базовий образ старіє сам по собі.
- Додайте в конвеєр перевірку вразливостей образу:
docker scout cves назва_образуабоtrivy image назва_образу.
Часті запитання
Чи потрібно оновлювати PHP на хості, якщо все в контейнерах?
Якщо на хості PHP не використовується — ні. Але перевірте: утиліти на кшталт composer або скрипти cron могли притягнути системний PHP.
Чи образ на Alpine теж вразливий?
Так, вразливий сам код PHP, а не дистрибутив. Оновлювати потрібно так само.
Як швидко перевірити весь парк контейнерів?
for c in $(docker ps -q); do printf '%s ' "$(docker inspect -f '{{.Name}}' $c)"; docker exec $c php -v 2>/dev/null | head -1 || echo 'без php'; done