Security-оновлення не закінчується на команді build або recreate. Після заміни PHP-образів потрібно довести, що локальне середовище справді працює на потрібних версіях і що оновлення не зламало залежності застосунку.
У моєму Laradock після оновлення я перевіряла не один контейнер, а весь ланцюжок: фактичну Compose-модель, PHP-FPM 8.3/8.4/8.5, workspace, phpMyAdmin, Laravel boot, MySQL, Redis, локальні сайти, published ports і build cache.
Саме така послідовність дала змогу закрити PHP patch як окрему завершену роботу, не називаючи при цьому весь infrastructure security аудит завершеним.
1. Перевіряємо effective Compose перед тестами
cd ~/Projects/laradock || exit 1 docker compose config -q echo "===== SERVICES ====="docker compose config --services echoecho "===== IMAGES ====="docker compose config --imagesПісля security-оновлення це моя перша контрольна точка. Compose-конфігурація повинна бути валідною, а список images має показувати саме зафіксовані patched images, а не старі базові tags.
У нашому випадку default Compose був переведений на захищену чотирифайлову модель, і після recreate вона продовжувала використовувати сім потрібних PHP-пов’язаних images.
2. Перевіряємо стан усіх потрібних контейнерів
cd ~/Projects/laradock || exit 1 docker compose ps -a echoecho "===== RUNNING CONTAINERS =====" docker ps \ --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'У фінальному стані PHP-FPM 8.3/8.4/8.5, phpMyAdmin та потрібні локальні залежності були запущені на patched images. Workspace 8.4 і 8.5 також працювали.
Workspace 8.3 залишився окремим винятком через конфлікт host port 5173. Його patched image був готовий, але контейнер не потрібно було запускати лише заради формального "все running".
3. Перевіряємо PHP у кожному активному runtime
cd ~/Projects/laradock || exit 1 for service in php-fpm php-fpm-84 php-fpm-85; do echo "===== $service =====" docker compose exec -T "$service" \ php -r 'echo PHP_VERSION, PHP_EOL;'doneНазва image tag або сервісу недостатня. Я хочу отримати PHP_VERSION безпосередньо з активного контейнера.
Для workspace використовую той самий принцип, але тільки для тих контейнерів, які вже повинні бути запущені. Не запускаю зупинений workspace виключно заради version check.
for service in workspace-84 workspace-85; do echo "===== $service =====" docker compose exec -T "$service" \ php -r 'echo PHP_VERSION, PHP_EOL;'done echo "===== phpMyAdmin =====" docker compose exec -T phpmyadmin \ php -r 'echo PHP_VERSION, PHP_EOL;'4. Перевіряємо PHP-FPM syntax
cd ~/Projects/laradock || exit 1 for service in php-fpm php-fpm-84 php-fpm-85; do echo "===== $service =====" docker compose exec -T "$service" \ php-fpm -tdoneНова версія PHP ще не доводить, що PHP-FPM може завантажити свою конфігурацію. php-fpm -t дає окрему перевірку syntax/configuration для runtime, який обслуговує застосунок.
5. Перевіряємо Docker health, але не плутаємо його зі станом застосунку
docker ps -q |while read -r id; do docker inspect \ --format '{{.Name}} | state={{.State.Status}} | health={{if .State.Health}}{{.State.Health.Status}}{{else}}not-configured{{end}}' \ "$id"doneНе кожен Laradock service має Docker healthcheck. Значення not-configured саме по собі не є помилкою.
І навпаки, healthy не замінює Laravel, MySQL або HTTP smoke. Docker health - лише один рівень перевірки.
6. Перевіряємо Laravel boot окремо від Docker
У нашому closeout базова application-перевірка складалася з двох частин: Composer platform check і Laravel bootstrap через artisan --version.
Так ми доводимо, що залежності сумісні з новим PHP і що застосунок може пройти базове завантаження.
cd ~/Projects/laradock || exit 1 docker compose exec -T php-fpm-85 \ php /var/www/icanup/vendor/composer/platform_check.php docker compose exec -T php-fpm-85 \ sh -lc 'cd /var/www/icanup && php artisan --version --no-ansi'7. Перевіряємо MySQL через сам Laravel
Те, що MySQL container має статус running, не доводить, що Laravel підключається до правильної локальної бази.
Тому для smoke я використовую read-only SELECT 1 після Laravel bootstrap. Перед такою перевіркою потрібно переконатися, що connection справді вказує на локальний Laradock MySQL, а не на віддалену базу.
cd ~/Projects/laradock || exit 1 docker compose exec -T php-fpm-85 \ sh -lc 'cd /var/www/icanup && php <<'\''PHP'\''<?php require 'vendor/autoload.php'; $app = require 'bootstrap/app.php'; $app->make( Illuminate\Contracts\Console\Kernel::class)->bootstrap(); $result = Illuminate\Support\Facades\DB::selectOne( 'SELECT 1 AS ok'8. Перевіряємо Redis на двох рівнях
Redis теж краще перевіряти не лише за статусом container. Спочатку можна переконатися, що сам Redis відповідає, а потім виконати application-level smoke через Laravel.
cd ~/Projects/laradock || exit 1 docker compose exec -T redis \ redis-cli pingcd ~/Projects/laradock || exit 1 docker compose exec -T php-fpm-85 \ sh -lc 'cd /var/www/icanup && php <<'\''PHP'\''<?php require 'vendor/autoload.php'; $app = require 'bootstrap/app.php'; $app->make( Illuminate\Contracts\Console\Kernel::class)->bootstrap(); try { $result = Illuminate\Support\Facades\Redis::connection()->ping();9. Перевіряємо Nginx і локальні сайти
docker exec \ laradock-nginx-1 \ nginx -tПісля технічних smoke checks я відкрила локальні сайти в браузері. Це не повний regression suite, але це важливий фінальний доказ, що Nginx, PHP-FPM, Laravel і локальні залежності разом обслуговують реальний HTTP request.
У нашому випадку всі потрібні локальні сайти після recreate відкривалися успішно.
10. Перевіряємо published ports
docker ps \ --format '{{.Names}}\t{{.Ports}}'sudo ss -H -ltnpПід час closeout ми окремо контролювали локальні bindings захищених сервісів. Вісім внутрішніх портів залишалися прив’язаними до localhost.
Водночас веб-порти Nginx та окремі dev-сервіси мали інший profile exposure, тому я не змішую "PHP patch завершений" з твердженням "усі мережеві ризики закриті".
11. Перевіряємо і очищаємо Docker builder cache окремо
docker system dfПісля багатьох security rebuilds build cache виріс приблизно до 16.33 GB. Ми очистили саме builder cache, не використовуючи ширший docker system prune.
docker builder prune \ --all \ --force docker system dfПісля cleanup build cache став 0B, а images, containers і volumes залишилися. Потім я знову перевірила image pins, щоб cleanup не став останньою неперевіреною зміною.
12. Фінальна перевірка після всіх змін
Перед тим як вважати PHP/Laradock update завершеним, я хочу мати підтвердження всіх ключових рівнів:
- effective Compose валідний і використовує patched image pins;
- PHP-FPM 8.3/8.4/8.5 показують очікувані patched versions;
- phpMyAdmin і потрібні workspace використовують patched runtime;
- PHP-FPM configuration проходить syntax check;
- Laravel проходить Composer platform check і базовий boot;
- Laravel виконує read-only MySQL
SELECT 1у локальній базі; - Redis відповідає і доступний застосунку;
- Nginx configuration валідна, а локальні сайти відкриваються;
- published ports перевірені, а внутрішні сервіси не стали випадково публічними;
- builder cache очищений, якщо це було заплановано, і image pins повторно перевірені після cleanup.
Після security-оновлення важливо перевірити не лише версію PHP, а весь шлях від Compose image до реального Laravel request.
Підсумок
У моєму випадку оновлення можна було вважати завершеним лише після того, як patched images пережили recreate, PHP runtime були перевірені, Laravel завантажувався, MySQL і Redis відповідали, локальні сайти відкривалися, порти були переглянуті, а build cache очищений без видалення потрібних images і volumes.
Це значно надійніший критерій, ніж просто побачити нову версію PHP після build.



