php artisan optimize у продакшені кешує кілька речей, і в Docker важливо розуміти, від чого залежить кожен кеш.
| Команда | Що кешує | Залежить від оточення? |
|---|---|---|
config:cache |
усю конфігурацію з підставленими env() |
так |
route:cache |
зареєстровані маршрути | зазвичай ні |
view:cache |
скомпільовані шаблони Blade | ні |
event:cache |
знайдені слухачі подій | ні |
При збиранні образу можна формувати те, що залежить лише від коду:
RUN composer install --no-dev --optimize-autoloader --no-interaction \
&& php artisan view:cache \
&& php artisan event:cache
Переваги: кеші вже в образі, контейнер стартує швидше, а помилка (наприклад, неправильний синтаксис Blade) з'являється на етапі збирання, а не на продакшені.
При старті контейнера - те, що залежить від змінних оточення:
#!/bin/sh
set -e
php artisan config:cache
php artisan route:cache
exec "$@"
Чому config:cache не в образі: змінні оточення (паролі, адреси, ключі) передаються при запуску. Кеш, зроблений при збиранні, міститиме значення середовища збирання, і контейнер ігноруватиме передані йому змінні.
route:cache - з нюансом: маршрути зазвичай не залежать від оточення, але якщо в routes/*.php є умови на config() чи env() (домен, увімкнені модулі), кеш при збиранні їх «заморозить». Безпечніше - при старті.
Ще кілька деталей:
- Composer:
--optimize-autoloader(чи--classmap-authoritative) - класична мапа класів замість пошуку файлів на кожен запит; - OPcache з
validate_timestamps=0- код у контейнері не змінюється, перевіряти час зміни файлів не потрібно; - права: кеші при старті пишуться в
bootstrap/cacheіstorageвід імені користувача застосунку - ці каталоги мають бути йому доступні для запису; - кілька реплік - кожна формує свій кеш при старті; це кілька сотень мілісекунд і не проблема.
Помилка, яку часто допускають: php artisan optimize у Dockerfile «щоб було швидше» - після чого продакшен-контейнер підключається до бази з порожнім паролем.