İç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.

Kısa cevap

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. İmajı non-root ve mümkün olduğunca dar kurmanın diğer yüzünü çok aşamalı build ve distroless kaydında ele almıştım.

Neden

  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 image’daki mount noktasının sahiplik/izinlerini kopyalar (çoğunlukla root çıkar ama bu garanti değildir); bind mount ise host dizininin sahipliğini olduğu gibi taşır. İkisinde de çözüm farklı.

  3. chmod 777 neden çözüm değil. 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 zaten yeterlidir; sorun izin bitlerinin darlığı değil, sahipliğin yanlış yerde olmasıdır.

Ne yapmalı

  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. Yeni dosyaların grubunu korumak için dizine setgid bit’i (chmod g+s) verin.

  2. Named volume’de entrypoint’te hedefli chown + drop yapın. 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 "$@"
  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.

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