PIE 1.5 змінив те, як інсталятор розширень PHP поводиться без людини поруч. Якщо Dockerfile чи CI-пайплайн ставить розширення проєкту через pie install з прапорцем --allow-non-interactive-project-install, після оновлення збірка може впасти: прапорець застарів і більше нічого не робить. Тепер пакет для кожного відсутнього розширення треба назвати явно через --select.
Коротко про PIE
PIE (PHP Installer for Extensions) - офіційний інсталятор розширень PHP від PHP Foundation, який замінює PECL, що тепер має статус застарілого. Він поширюється як PHAR і працює схоже на Composer, тільки ставить не пакети у vendor, а розширення в саму інсталяцію PHP. Розширення - це звичайні Composer-пакети на Packagist: phpredis/phpredis, xdebug/xdebug, apcu/apcu. На Windows PIE бере вже зібрані DLL, на Linux і macOS збирає з вихідного коду.
Для тих, хто досі на pecl, переклад команд майже механічний:
pecl install xdebug → pie install xdebug/xdebug;
pecl list → pie show;
pecl search → pie search <term>;
pecl upgrade-all → pie upgrade.
Повна таблиця відповідностей є в документації PIE.
Як PIE читає composer.json проєкту
Якщо запустити pie install без аргументів у теці проєкту, PIE читає composer.json і перевіряє кожну вимогу ext-*. Наприклад, для застосунку на Laravel, який працює з Redis через PhpRedis, а покриття рахує Xdebug:
{
"require": {
"ext-redis": "*"
},
"require-dev": {
"ext-xdebug": "*"
}
}
Рядок ext-redis лише каже Composer, що застосунок не працюватиме без розширення redis. Сам він нічого не встановлює: composer install просто відмовиться ставити залежності, якщо розширення немає. Додавати його варто, лише якщо ви справді користуєтеся PhpRedis - Laravel вміє працювати з Redis і через Predis, бібліотеку на чистому PHP, якій розширення не потрібне.
Проблема в тому, що в composer.json розширення названі за назвою розширення (redis), а PIE встановлює пакети (phpredis/phpredis). Одне розширення може надавати кілька пакетів - наприклад, форк. Тому в інтерактивному режимі PIE питає, який пакет ставити, навіть якщо варіант один.
Що зламалося в неінтерактивному режимі
До 1.5 у CI можна було передати --allow-non-interactive-project-install: якщо підходящий пакет був один, PIE ставив його сам, якщо кілька - падав. У задачі #624 мейнтейнери пояснили, чому від цього відмовилися: розробник має повністю контролювати, що потрапляє в його PHP, а автовибір цього не гарантує.
Тож у PR #633 прапорець став застарілим і нічого не робить, а замість нього з'явився --select. Правила такі:
- ліворуч - назва розширення без префікса
ext-, праворуч - пакет: --select=redis=phpredis/phpredis;
- для кожного розширення окремий
--select;
- якщо розширення відсутнє і
--select для нього немає, неінтерактивний запуск падає, навіть коли підходящий пакет лише один;
- якщо розширення вже встановлене,
--select для нього просто ігнорується.
Це стосується лише встановлення за composer.json. Команда на кшталт pie install phpredis/phpredis уже називає пакет і працює як раніше.
Нова команда для Dockerfile
Для продакшн-образу прикладу вище команда тепер виглядає так:
pie install --no-interaction --no-dev \
--select=redis=phpredis/phpredis
--no-dev (PR #710) пропускає розширення, оголошені лише в require-dev. Саме з цього все й почалося: у задачі #707 користувач скаржився, що PIE ставив і вмикав Xdebug у продакшн-образі, бо перевіряв і require, і require-dev.
Не плутайте його з composer install --no-dev. Прапорець PIE стосується тільки перевірки розширень: він не видаляє вже встановлені розширення і ніяк не впливає на PHP-пакети у vendor. У Dockerfile вам знадобляться обидва.
Для середовища розробки, де потрібні обидва розширення, - два --select:
pie install --no-interaction \
--select=redis=phpredis/phpredis \
--select=xdebug=xdebug/xdebug
Ще одна деталь: у неінтерактивному режимі PIE не ставить відсутні інструменти збірки (gcc, make, autoconf, phpize...), якщо не передати --auto-install-build-tools. Нова команда pie check-build-tools (PR #673) показує, чого бракує, ще до встановлення - зручно як окремий крок у CI.
Кілька розширень однією командою і pie upgrade
Якщо Dockerfile ставить розширення за назвами пакетів, а не за composer.json, тепер їх можна передати разом (PR #642):
pie install phpredis/phpredis xdebug/xdebug
Раніше це закінчувалося помилкою Too many arguments і доводилося писати окремий pie install на кожне розширення. Точну назву пакета підкаже pie search xdebug (PR #674).
pie upgrade (PR #666) оновлює розширення, встановлені через PIE, у цільовій інсталяції PHP. Він тримається обмежень версій, з якими кожне розширення ставили:
pie install 'phpredis/phpredis:^6.0'
# згодом
pie upgrade
Тут pie upgrade підтягне нові релізи 6.x, але не 7.0 - для мажорної версії треба знову виконати pie install з новим обмеженням. До Laravel і пакетів у vendor команда стосунку не має.
Дрібніше, але приємно: з 1.5 повторне встановлення тієї самої версії розширення з тими самими опціями configure нічого не робить, тож повторний запуск у CI не перезбирає розширення марно.
Що зробити зараз
- Перевірте, яку версію PIE бере збірка. Тег Docker-образу
ghcr.io/php/pie:bin завжди вказує на останню стабільну версію. Якщо ваш Dockerfile бере саме його, 1.5 у вас уже стоїть, хоч ви нічого й не оновлювали.
- Знайдіть
--allow-non-interactive-project-install у Dockerfile і CI-конфігах та замініть його на --no-interaction з --select для кожного розширення, якого немає в базовому образі.
- Додайте
--no-dev у продакшн-збірку, якщо в require-dev є Xdebug, PCOV чи інші розширення для розробки.
- Закріпіть версію. З 1.5 публікуються теги на кшталт
1.5-bin і 1.5.5-bin: так наступний реліз не змінить поведінку збірки без попередження.
- Оновіться щонайменше до 1.5.5. 30 жовтня вийшли 1.5.5 і 1.4.12 з виправленням безпеки (GHSA-4538-pqqf-mv67), тож на гілці 1.4 теж варто бути на останній версії.
Якщо ж ви досі ставите розширення через pecl або docker-php-ext-install і --select вас поки не стосується, 1.5 - хороший момент спробувати PIE: явний список розширень у Dockerfile разом з --no-dev робить образ передбачуванішим, ніж будь-який автовибір.