Laravel пише у два каталоги:
storage/- логи, скомпільовані шаблони Blade, файловий кеш, сесії, завантаження на дискlocal;bootstrap/cache/- кеш конфігурації, маршрутів, подій,packages.php,services.php.
Типова помилка:
The stream or file "/var/www/html/storage/logs/laravel.log" could not be opened in append mode: Failed to open stream: Permission denied
Причина: процес PHP працює від одного користувача (www-data, UID 33 в офіційних образах Debian чи 82 в Alpine), а файли належать іншому - найчастіше root, бо COPY у Dockerfile за замовчуванням створює файли власника root.
Виправлення в Dockerfile:
COPY --chown=www-data:www-data . /var/www/html
# або для вже скопійованих файлів - лише каталоги для запису
RUN chown -R www-data:www-data storage bootstrap/cache \
&& chmod -R ug+rwX storage bootstrap/cache
USER www-data
--chown при COPY кращий за окремий RUN chown -R: окремий chown створює ще один шар з копією всіх файлів і збільшує образ.
Чого не робити:
chmod -R 777 storage- «працює», але дає запис усім і маскує справжню проблему;- запускати PHP від
root, щоб «не було проблем з правами» - якщо зловмисник виконає код, він отримає root у контейнері.
Типові пастки:
- bind mount у розробці (
./:/var/www/html) - файли мають власника з хоста (UID 501 на macOS, 1000 на Linux). На Linux процес у контейнері з іншим UID не може писати. Рішення - запускати PHP з UID розробника (Sail робить це черезWWWUSER); - том для storage створюється при першому запуску з правами
root- потрібно задати власника в образі до оголошення тому чи при старті; - файли, створені
php artisanвід root черезdocker exec(наприклад, кеш конфігурації чи лог) потім недоступні дляwww-data. Виконувати команди від того самого користувача:docker exec -u www-data app php artisan ....