İçeriğe geç
Muhammet Şafak
en
Soran: Barış Cevaplandı:

Container'ı non-root çalıştırınca mount edilen storage dizinine yazamıyorum, izinleri nasıl çözerim?


Soru

Laravel uygulamamı Docker'da çalıştırıyorum ve güvenlik için image'ı root yerine kendi oluşturduğum bir kullanıcıyla (non-root) çalıştırmaya geçtim. Ama bunu yaptıktan sonra `storage/` altına yazma işlemleri patlamaya başladı: log yazamıyor, cache ve session dosyaları oluşmuyor, sürekli "Permission denied" alıyorum. Kurulumum şöyle: `php:8.3-fpm-alpine` tabanlı bir image, uygulama kodu image'ın içinde, ama `storage/` dizinini kalıcılık için bir volume olarak mount ediyorum. Container root iken hiç sorun yoktu. Non-root kullanıcıda izinleri, `chmod 777` yapmadan, doğru şekilde nasıl çözerim?

Cevap

Kısa cevap: Sorun izin bitlerinde değil, UID eşleşmesinde. Container’daki kullanıcının sayısal UID’si, mount edilen dizinin sahibiyle uyuşmuyor; root iken çalışmasının sebebi de root’un (UID 0) her şeye yazabilmesiydi. Çözüm chmod 777 değil, sahipliği hizalamak.

  1. Kök neden: UID, kullanıcı adı değil. Linux izinlerinde önemli olan sayısal UID/GID’dir. Image’daki app kullanıcısı UID 1000 olabilir; ama mount ettiğiniz dizin host’ta başka bir UID’ye aitse kernel yazmayı reddeder. İsim eşleşmesi hiçbir şey ifade etmez.
  2. Named volume mü, bind mount mu? Named volume Docker tarafından yönetilir ve ilk oluşumda içeriği root sahipliğiyle doldurur; bind mount ise host dizininin sahipliğini olduğu gibi taşır. İkisinde de çözüm farklı.
  3. Entrypoint’te hedefli chown + drop. Container’ı root olarak başlatın, yalnızca yazılabilir olması gereken dizinleri chown edin, sonra kullanıcıya düşün:
#!/bin/sh
# entrypoint (root ile başlar, sonra app'e düşer)
chown -R app:app storage bootstrap/cache
exec su-exec app "$@"
  1. Bind mount’ta build-time UID’yi hizalayın. Dockerfile’da ARG UID/ARG GID ile kullanıcıyı host’unuzun UID’siyle oluşturun, kodu COPY --chown=app:app ile kopyalayın. Böylece entrypoint hilesine bile gerek kalmadan sahiplik baştan doğru olur.
  2. chmod 777’den kaçının. Bu bir güvenlik gerilemesidir ve non-root’a geçme amacınızı boşa çıkarır. Group-writable (g+w) izin ile doğru grup üyeliği yeterli; yeni dosyaların grubunu korumak için dizine setgid bit’i (chmod g+s) verin.
  3. Kalıcı state’i doğru yere koyun. Birden çok replica çalıştıracaksanız storage/’ı paylaşımlı bir dosya sistemi üzerinden değil, session/cache için Redis’e ve dosyalar için S3 gibi bir object storage’a taşıyın; volume izin derdi tamamen kaybolur.

Sonuç: Ben olsam build-time ARG UID ile kullanıcıyı sabitler, COPY --chown kullanır ve named volume’ler için entrypoint’te yalnızca storage ve bootstrap/cache’i chown edip su-exec ile app’e düşerdim. Uzun vadede ise kalıcı veriyi mümkün olduğunca S3/Redis’e taşıyıp container’ı gerçekten stateless tutardım.

Etiketler: #docker#güvenlik#laravel
Paylaş:

Yorumlar

Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.

Diğer Sorular

Tüm sorular

Sitede Ara

Yazı, proje ve sayfalarda arama yapmak için yazmaya başlayın.

Esc ile kapat Pagefind ile güçlendirildi