Після того як я додала MinIO до Laradock, наступним кроком стало підключення сховища до Laravel.
На цьому місці легко створити окремий MinioStorageService, додати спеціальні методи для запису і читання файлів та поступово прив’язати застосунок до конкретного сховища.
Але MinIO підтримує S3-сумісний API, а Laravel уже вміє працювати з S3 через Filesystem.
Тому я не додавала новий спосіб роботи з файлами. Для Laravel MinIO залишився звичайним s3 disk з іншою адресою сховища.
Я не хочу, щоб прикладний код знав про MinIO
$minioStorage->put( $path, $contents,); $minioStorage->delete( $path,);Storage::disk('s3')->put( $path, $contents,); Storage::disk('s3')->delete( $path,);У другому варіанті прикладний код знає лише про файловий disk.
Йому не потрібно знати, чи за цим disk зараз стоїть MinIO, AWS S3 або інше S3-сумісне сховище.
Локальне середовище може використовувати MinIO, а інше середовище - іншу інфраструктуру без переписування кожного місця, де застосунок працює з файлами.
Основою залишається стандартний disk s3
's3' => [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION'), 'bucket' => env('AWS_BUCKET'), 'endpoint' =>Окремого driver=minio тут немає.
Драйвер залишається s3.
Відрізняється лише інфраструктурна конфігурація: адреса S3-сумісного API, облікові дані, регіон, бакет і спосіб побудови адрес.
Локальні відмінності залишаються в конфігурації середовища
AWS_ACCESS_KEY_ID=laradockAWS_SECRET_ACCESS_KEY=laradockAWS_DEFAULT_REGION=us-east-1 AWS_BUCKET=local-files AWS_ENDPOINT=http://minio:9000 AWS_USE_PATH_STYLE_ENDPOINT=trueУ прикладному коді мені не потрібна умова на кшталт if local then MinIO.
Саме середовище повідомляє Laravel, де знаходиться файлове сховище.
У моєму локальному Docker-середовищі адреса дорівнює http://minio:9000.
Причину, чому localhost усередині контейнера не веде до MinIO, я розібрала окремо: контейнер застосунку знаходить сусідній сервіс через мережу Docker та ім’я сервісу.
Адреса змінює місце призначення, а не контракт застосунку
Application | vStorage::disk('s3') | vLaravel Filesystem | vS3 driver | vconfigured endpoint | +--> MinIO locally |AWS_ENDPOINT відповідає лише на питання, де знаходиться S3-сумісний API.
Він не змінює спосіб, яким прикладний код просить записати, прочитати або видалити файл.
Саме тому адресу MinIO я залишаю в конфігурації, а не передаю в сервіси предметної області.
Для локального MinIO використовую бакет у шляху
http://minio:9000/local-files/example.txt | +--> bucketДля локальної адреси minio:9000 зручно використовувати AWS_USE_PATH_STYLE_ENDPOINT=true.
Тоді назва бакета передається в шляху запиту.
Для локальної Docker-мережі це простіше, ніж вимагати окреме DNS-ім’я для кожного бакета.
Laravel не створює бакет лише тому, що його назва є в .env
AWS_BUCKET=local-files лише повідомляє Laravel, який бакет використовувати.
Сам бакет має існувати у сховищі.
Тому після налаштування MinIO я окремо перевіряю, що потрібний бакет створений, і лише після цього тестую запис із Laravel.
Першу перевірку роблю через стандартний Storage
Storage::disk('s3')->put( 'checks/minio.txt', 'MinIO works',); Storage::disk('s3')->exists( 'checks/minio.txt',); Storage::disk('s3')->get( 'checks/minio.txt',); Storage::disk('s3')->delete( 'checks/minio.txt',);Для першої перевірки мені не потрібен окремий контролер або спеціальний MinIO-клієнт.
Я хочу довести базовий цикл через той самий API, яким користуватиметься застосунок: записати файл, перевірити його існування, прочитати і видалити.
Якщо ці операції проходять через Storage::disk('s3'), базове підключення Laravel до MinIO вже працює.
Після запису перевіряю файл і в MinIO
Після put() я відкриваю потрібний бакет у веб-консолі MinIO і перевіряю шлях checks/minio.txt.
Це підтверджує, що Laravel справді записав об’єкт у потрібне S3-сумісне сховище, а не випадково використав інший disk.
Після перевірки тестовий файл видаляється через той самий Storage.
Після зміни .env перевіряю кеш конфігурації
php artisan config:clearПравильне значення в .env ще не гарантує, що саме його зараз використовує Laravel.
Якщо конфігурація була закешована раніше, застосунок може продовжувати працювати зі старою адресою або старим бакетом.
Тому при локальному налаштуванні я перевіряю і цей шар.
Дивлюся, яку конфігурацію Laravel реально отримав
config( 'filesystems.disks.s3.endpoint',); config( 'filesystems.disks.s3.bucket',); config( 'filesystems.disks.s3.use_path_style_endpoint',);Коли з’єднання не працює, я не обмежуюся переглядом .env.
Спочатку дивлюся, яке значення реально потрапило в filesystems.disks.s3.
Це швидко відділяє помилку конфігурації від проблеми мережі або самого S3-запиту.
Адресу MinIO не записую в прикладний сервіс
$client->put( 'http://minio:9000/local-files/'.$path, $contents,);minio:9000 є правильною адресою для конкретного локального середовища.
Але це не робить її частиною логіки застосунку.
Якщо записати цю адресу прямо у файловий сервіс, перехід на інше S3-сумісне сховище вже вимагатиме змін коду.
Через Laravel Filesystem ця деталь залишається в конфігурації.
Окремий файловий сервіс може бути потрібен, але не через MinIO
final readonly class PrivateAttachmentStorage{ public function store( string $path, string $contents, ): void { Storage::disk('s3')->put( $path, $contents, ); }}Окремий клас для роботи з файлами може бути цілком доречним.
Наприклад, якщо він визначає шлях приватних вкладень, правила заміни файла, очищення старого об’єкта або інші вимоги застосунку.
Але причина його існування тоді в поведінці системи, а не в тому, що локально використовується MinIO.
Усередині такий клас усе одно може працювати через Storage::disk('s3').
Найважливіше - однаковий прикладний код у різних середовищах
Локально Storage::disk('s3') | vMinIO Інше середовище Storage::disk('s3') | vS3-сумісне сховище Саме заради цього я підключаю MinIO через стандартний S3 disk.
Локально отримую бакети, об’єкти, HTTP API та іншу поведінку S3-сумісного сховища.
При цьому код збереження файла не отримує окремої гілки лише для MinIO.
Адреса для Laravel і посилання для браузера - різні задачі
http://minio:9000 доступний контейнеру Laravel, але браузер користувача не знає внутрішнього Docker-імені minio.
Тому серверне підключення до S3 і формування посилань для браузера я не змішую в одну проблему.
На цьому етапі достатньо довести, що Laravel правильно читає і записує файли.
Тимчасові посилання на приватні файли мають власні правила і заслуговують окремого матеріалу.
Що я перевіряю після підключення MinIO до Laravel
Мій короткий список:
- Чи використовується стандартний driver s3?
- Чи адреса сховища береться з конфігурації?
- Чи контейнер Laravel бачить
http://minio:9000? - Чи вказані правильні облікові дані?
- Чи існує потрібний бакет?
- Чи ввімкнений режим адресації через шлях?
- Чи Laravel бачить нові значення після зміни
.env? - Чи працюють
put(),exists(),get()іdelete()? - Чи не потрапили адреса MinIO або спеціальна MinIO-логіка в прикладний код?
MinIO змінює інфраструктуру, а не файловий контракт Laravel
Після такого підключення в прикладному коді не з’являється новий спосіб роботи з файлами.
Laravel як використовував Storage::disk('s3'), так і продовжує його використовувати.
MinIO лише надає локальне S3-сумісне сховище з власною адресою, бакетом і обліковими даними.
У результаті я можу перевіряти S3-поведінку локально, не створюючи окрему файлову реалізацію лише для MinIO.
Якщо інфраструктура вже підтримує потрібний контракт, я краще підключу її до стандартної абстракції Laravel, ніж створю ще одну абстракцію через назву конкретного сервісу.
Мені не потрібен окремий спосіб зберігати файли в MinIO. Мені потрібен стандартний S3 disk, який у локальному середовищі використовує MinIO.



