Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Де зберігати файли, завантажені користувачами, якщо Laravel працює в контейнерах?

Файлова система контейнера тимчасова. Усе, що записано в контейнер (наприклад, у storage/app/public на диску local), зникає при його перестворенні - тобто при кожному деплої.

Варіант 1 - том Docker:

services:
  app:
    volumes:
      - uploads:/var/www/html/storage/app
volumes:
  uploads:
  • дані переживають перестворення контейнера;
  • працює лише на одному сервері: другий сервер чи друга репліка на іншому хості цих файлів не бачать;
  • бекапи томів - окрема турбота;
  • віддавати файли користувачам доводиться через застосунок або Nginx з доступом до тому.

Варіант 2 - об'єктне сховище (рекомендовано): S3, Cloudflare R2, DigitalOcean Spaces, MinIO.

// config/filesystems.php
'disks' => [
    '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' => env('AWS_ENDPOINT'),
    ],
],
$path = $request->file('avatar')->store('avatars', 's3');
$url = Storage::disk('s3')->url($path);
  • контейнери без стану: будь-яку кількість реплік на будь-яких серверах можна знищити й перестворити;
  • файли віддаються з CDN, а не через застосунок;
  • надійність і бекапи - на боці провайдера;
  • приватні файли - через тимчасові підписані посилання (temporaryUrl).

Що ще не повинно жити в контейнері:

  • сесії - в Redis чи базі, а не в файлах, інакше користувача розлогінить після деплою чи при переході на іншу репліку;
  • кеш - Redis чи база; файловий кеш у кожній репліці свій і не очищується разом;
  • логи - в stderr, звідки їх збирає Docker.

Локальна розробка: MinIO в Compose імітує S3, і застосунок працює з тим самим драйвером, що й у продакшені.

Важлива деталь Laravel: php artisan storage:link створює символьне посилання public/storage → storage/app/public. З S3 воно не потрібне, а з томом - має існувати в образі чи створюватися при старті.

Докладніше в документації: Laravel: файлове сховище

Схожі питання