Docker Compose PUID ve PGID nedir ve nasıl kullanılır?
PUID ve PGID Docker ayarı değildir. linuxserver.io imajlarında dosya sahipliği sorunlarını çözmek için kullanılan bir yöntemdir. 911 hatasını giderme yollarını öğrenin.
PUID ve PGID değerlerinin işlevi
PUID ve PGID, belirli container imajlarının başlangıçta okuduğu iki ortam değişkenidir. Docker'ın kendisi bu değişkenleri hiçbir zaman kontrol etmez. Bunlar, linuxserver.io imajları ve diğer bazı imajlar tarafından kullanılan bir gelenektir; dolayısıyla bu değişkenleri okumak üzere tasarlanmamış bir imaj, bunları sessizce görmezden gelir.
Bir linuxserver.io imajının içerisinde, oluşturulma aşamasında UID (kullanıcı kimliği) 911 ve GID (grup kimliği) 911 ile tanımlanmış abc adında bir kullanıcı bulunur. Container root yetkileriyle başlar, init betiklerini çalıştırır ve bu betiklerden biri, başka hiçbir işlem gerçekleşmeden önce ilgili kullanıcının kimlik numaralarını yeniden düzenler:
groupmod -o -g "${PGID}" abc
usermod -o -u "${PUID}" abc-o bayrağı, başka bir yerde halihazırda kullanımda olan bir kimliğin kullanılmasına izin verir. Bu işlemin ardından init süreci yetkilerini düşürür ve uygulamayı abc kullanıcısı olarak çalıştırır. Dolayısıyla PUID=1000 hiçbir zaman Docker'a ulaşmaz. Bu değişken, uygulama başlamadan önce container içindeki bir kullanıcının kimlik numarasını yeniden düzenler; bu da uygulamanın yazdığı her dosyanın diskinizde 1000 sahibiyle kaydedilmesi anlamına gelir. PUID değerini boş bırakırsanız abc varsayılan olarak 911 değerini korur; yapılandırılmamış bir bind mount dizininin 911:911 sahibiyle oluşturulmuş dosyalarla dolmasının nedeni budur.
id ile iki numaranızı alın
Bu komutu, veri dizinlerinin sahibi olan kullanıcı ile ana makine üzerinde çalıştırın:
iduid=1000(deploy) gid=1000(deploy) groups=1000(deploy),27(sudo),988(docker)uid sizin PUID değeriniz, gid ise PGID değerinizdir. Bir betik için id -u ve id -g komutları sadece sayıları yazdırır. Çoğu yeni VPS imajında ilk kullanıcı hesabı 1000:1000 değerindedir ancak bunu varsaymayın. Yeniden yapılandırılmış bir sunucu veya sonradan eklenen ikinci bir hesap 1001 veya daha yüksek bir değer verir; burada yapılacak bir yanlışlık tüm hatanın kaynağıdır. Servisleriniz kendi oturum açma kullanıcınız yerine özel bir servis hesabı altında çalışıyorsa, id thatuser komutunu çalıştırın ve sayıları oradan alın.
Dosyalarınız neden 911:911 olarak görünüyor
ls -l, o kimliğe karşılık gelen bir ana makine hesabı bulunamadığında isim yerine sayısal bir kimlik yazdırır. Sunucunuzda UID 911 olan hiçbir hesap yoktur, bu nedenle yazdırılacak bir isim bulunmamaktadır. Belirsizliği gidermek ve her zaman sayıları görmek için ls -ln kullanın:
ls -ln /srv/appdata/sonarrdrwxr-xr-x 2 911 911 4096 Aug 7 09:12 Backups
-rw-r--r-- 1 911 911 512 Aug 7 09:12 config.xmlBu çıktı, container'ın yerleşik varsayılan ayarlarla çalıştığını belirtir. Tahmin etmek yerine container içinden durumu doğrulayın:
docker exec sonarr id abc
docker compose logs sonarr | head -n 25linuxserver init süreci, sonucunu başlangıç günlüğünde iki satır halinde yazdırır:
User UID: 911
User GID: 911Eğer PUID=1000 değişkenini Compose dosyanızda ayarlamanıza rağmen bu satırlarda 911 yazıyorsa, değişken container'a ulaşmamıştır. Bunun yaygın nedeni, docker-compose.yml dosyasını düzenledikten sonra docker compose restart komutunu çalıştırmanızdır; bu komut, mevcut container'ı orijinal ortam değişkenleriyle yeniden kullanır. Ortam değişkeni değişiklikleri, container'ı yeniden oluşturan docker compose up -d komutunu gerektirir.
Container tarafından yazılan bir dosyanın neden silinemediği
Çekirdek, isimleri değil sayıları karşılaştırır. Kabuğunuz UID 1000 olarak çalışır. Dosya ise UID 911'e aittir. Dosyayı barındıran dizin drwxr-xr-x yolundadır ve o da 911'e aittir; bu nedenle grup ve diğer kullanıcılar okuma ve çalıştırma yetkisine sahip olsalar da yazma yetkileri yoktur. Bir dosyayı silmek için dosyanın kendisine değil, bulunduğu dizine yazma izninizin olması gerekir. Bu yüzden dosya zararsız görünse bile şu hatayı alırsınız:
rm: cannot remove '/srv/appdata/sonarr/config.xml': Permission deniedYazma işlemi yapan bir container, aynı duvara diğer taraftan çarpar. Eğer ana makinedeki dizin 755 modunda sizin kullanıcınıza aitse ve uygulama 911 kullanıcısı olarak çalışıyorsa, ilk yazma girişimi Permission denied hatasıyla başarısız olur ve uygulama bunu kendi hata mesajlarıyla raporlar. Sonarr veya Radarr gibi bir .NET uygulamasında bu durum UnauthorizedAccessException: Access to the path '/data/downloads' is denied olarak görünür. Dosyanın önündeki izin dizgisi, üç izin kümesinden hangisine göre değerlendirildiğinizi gösterir; drwxr-xr-x ifadesini doğru okumak, bu hatanın gizemli olmaktan çıkıp anlaşılır hale gelmesini sağlar.
Bu durum özellikle bir bind mount sorunudur. Docker, boş bir named volume oluşturup bunu imaj içinde var olan bir yolun üzerine bağladığında, o yolun içeriğini sahiplik ve izin bitleri dahil olmak üzere volume içine kopyalar; böylece uygulama zaten sahip olduğu bir dizin bulur. Bind mount ise bu işlemin hiçbirini görmez: Docker, ana makinedeki dizininizi olduğu gibi bağlar. Bu fark, bind mount yönteminin named volume yönteminden ne zaman daha avantajlı olduğunu bilmenin pratik nedenlerinden biridir.
Hatalı yapılandırılmış bir dizini düzeltme
PUID ve PGID değerlerini ayarlamak, uygulamanın bundan sonraki davranışını değiştirir. Bu işlem, diskte halihazırda bulunan dosyaları geriye dönük olarak düzeltmez. Stack'i durdurun, sahiplik bilgilerini manuel olarak düzeltin ve ardından tekrar başlatın:
docker compose down
sudo chown -R 1000:1000 /srv/appdata/sonarr
docker compose up -dSayıları yazmak istemiyorsanız sudo chown -R "$(id -u):$(id -g)" /srv/appdata/sonarr kullanın. Bu işlemi container durdurulmuş durumdayken yapın; çünkü özyinelemeli (recursive) bir chown işlemi sırasında yazma aşamasında olan çalışan bir uygulama, dizin ağacının yarım yamalak düzeltilmesine ve ikinci bir kafa karıştırıcı hata döngüsüne yol açabilir.
PUID ve PGID'nin çözemediği durumlar
Her şeyi doğru yapan kullanıcıların dahi takıldığı nokta burasıdır. linuxserver init süreci, başlangıçta tam olarak üç yolu chown komutuyla düzenler: /app, /config ve /defaults. Medya bağlama noktalarınız (mounts) bu listede yer almaz. /data, /downloads ve /tv yolları uygulamaya olduğu gibi aktarılır. Dolayısıyla, bu bağlama noktalarının ana makine tarafındaki sahiplik bilgisi container kullanıcısının yazma yetkisiyle uyuşmuyorsa, container sorunsuz başlar, banner kısmında doğru UID değerini gösterir ancak ilk içe aktarma (import) işleminde hata verir.
Bu beklenen davranıştır. On iki terabaytlık bir medya kütüphanesinde her container başlangıcında özyinelemeli (recursive) bir chown işlemi felaketle sonuçlanır. Bu durum, medya dizinlerinin yönetiminin sizin sorumluluğunuzda olduğu anlamına gelir; izin hatalarının asıl yaşandığı yerler de bu bağlama noktalarıdır.
Kullanıcıyı denetlemenin üç yolu ve her birinin kullanım alanları
PUID ve PGID ortam değişkenleri
Bu yöntem yalnızca giriş noktası (entrypoint) bu değişkenleri okuyan imajlarda çalışır. Popülerdir çünkü container hala root olarak başlar, kendi kurulumunu yapar, /config hatalarını düzeltir ve ancak o aşamadan sonra yetkilerini düşürür. Docker Mods ve özel init betikleri çalışmaya devam eder. Dezavantajı, bir platform özelliğinden ziyade bir kurala güveniyor olmanızdır ve değişken isimleri projeler arasında standart değildir.
Compose içindeki user: anahtarı
Bu gerçek bir Docker özelliğidir ve her imajda çalışır; çünkü container çalışma zamanı (runtime) bunu imajın kendi kodu çalışmadan önce uygular:
services:
sonarr:
image: lscr.io/linuxserver/sonarr:latest
user: "1000:1000"Süreç hiçbir an root olarak çalışmaz, bu da gerçek bir güvenlik kazanımı sağlar. Ancak giriş noktasında root yetkisi gerektiren her şeyi bozar. linuxserver imajlarında proje bunu "makul çaba" esasına göre ve yalnızca test ettiği imajlar için destekler; kısıtlamalar bellidir: PUID ve PGID etkisiz hale gelir, Docker Mods çalışmaz, özel servisler çalışmaz ve bağlanan tüm birimlerin (volume) izinlerinden siz sorumlu olursunuz. Belgelenen kullanım biçimi, bu bayrağı yazılabilir bir /run ile eşleştirir:
user: 1000:1000
tmpfs:
- /run:uid=1000,gid=1000,exec
security_opt:
- no-new-privileges=trueKozmetik bir yan etki kullanıcıları şaşırtabilir. Sayısal bir user:, container içindeki /etc/passwd dosyasında eşleşen bir kayda sahip değildir, bu nedenle araçlar whoami: cannot find name for user ID 1000 raporlar. Kimlik (ID) geçerlidir ve dosya erişimi normal şekilde çalışır. Yalnızca isim çözümleme başarısız olur.
Rootless Docker
Rootless Docker, daemon sürecini yetkisiz kullanıcınız olarak çalıştırır, böylece sunucuda hiçbir şey gerçek root olarak çalışmaz. Bu durum sahiplik aritmetiğini tamamen değiştirir. Container içindeki UID 0, rootless Docker'ı çalıştıran kullanıcının ana makine UID'si ile eşleşir. 1 veya daha büyük herhangi bir n için container UID n, subuid + (n - 1) ile eşleşir; burada subuid, /etc/subuid ve /etc/subgid dosyalarında size ayrılan aralığın başlangıcıdır. Docker burada en az 65,536 adet alt kimlik (subordinate ID) bekler.
Bu eşleştirmeyi tekrar inceleyin, çünkü genel tavsiyeyi tersine çevirir. Rootless Docker altında root olarak yazan bir container, sizin sahip olduğunuz dosyalar üretir. UID 1000 olarak yazan bir container ise kabuğunuzun erişemeyeceği, 100999 civarında bir alt kimliğe sahip dosyalar üretir. Bu nedenle, rootful bir daemon üzerinde doğru olan PUID değeri burada yanlıştır. İki mekanizma aynı sorunu farklı katmanlarda çözer; bunları kontrol etmeden üst üste kullanmak, kullanıcıların silmek için sudo gerektiren dizinlerle karşılaşmasına neden olur. Rootless kullanacaksanız, bir kütüphaneyi taşımadan önce kendi sunucunuzda yazılan bir dosyanın sahipliğini test edin.
Tek bir VPS üzerindeki çoğu self-hosted yığını için, rootful bir daemon üzerinde PUID ve PGID kullanmak pragmatik bir seçimdir; çünkü imajlar bunun için oluşturulmuş ve belgelenmiştir. user: yöntemine, imajın README dosyası bunun için test edildiğini belirttiğinde veya PUID desteği hiç olmayan resmi bir upstream imajı çalıştırdığınızda başvurun. Tek bir VPS üzerinde self-hosted AFFiNE örneği gibi bir doküman çalışma alanı bu son duruma girer; çünkü container'larının hiçbiri PUID okumaz ve veritabanı dizini ile yüklenen dosyaların sahipliği, ortam bloğundaki herhangi bir şey tarafından değil, çalışma zamanı tarafından belirlenir.
Medya yığını örneği: container'lar arasında paylaşılan tek bir grup
Sonarr, Radarr ve bir indirme istemcisi içeren arr medya yığını, bu konunun teoriden pratiğe geçtiği yerdir. İndirme istemcisi tamamlanan dosyayı /data/downloads dizinine yazar. Sonarr ise bu dosyayı /data/media dizinine hardlink ile bağlar veya taşır. Hardlink işleminin çalışabilmesi için her iki container'ın da aynı dizin ağacına yazma erişimine sahip olması gerekir. Eğer indirme istemcisi 1000, Sonarr ise 1001 kullanıcı kimliğiyle çalışıyorsa, taraflardan biri diğerinin sadece okuyabildiği dosyaların sahibi olur.
Çözüm, yığındaki her container'ın PGID olarak kullandığı paylaşımlı bir gruptur:
sudo groupadd -g 13000 media
sudo usermod -aG media deploy
sudo chown -R deploy:media /srv/media
sudo find /srv/media -type d -exec chmod 2775 {} +
sudo find /srv/media -type f -exec chmod 0664 {} +2775 içindeki baştaki 2, setgid bitidir. Bir dizin üzerinde bu bit, içinde oluşturulan her yeni dosya ve alt dizinin, oluşturucunun birincil grubu yerine media grubunu miras alması anlamına gelir. Böylece chown komutunu tekrar çalıştırmanıza gerek kalmadan yapılandırma yeni indirmelerde de geçerli olur. Kendi erişiminizi kontrol etmeden önce oturumu kapatıp açın veya newgrp media komutunu çalıştırın; usermod -aG ile eklenen bir grup, halihazırda açık olan bir kabuk oturumunda görünmez.
Container içinde groupmod -o -g 13000 abc, abc grubunu 13000 olarak yeniden numaralandırır; böylece abc, ana makinenizdeki media grubuyla aynı GID değerine sahip dosyalar yazar. Yığındaki her container kendi PUID değerini korur ancak aynı PGID değerini paylaşır.
Ardından yığındaki her linuxserver container'ı için UMASK=002 değerini ayarlayın. İnsanların gözden kaçırdığı adım budur. Bu imajlardaki varsayılan değer UMASK=022'dir; bu değer her yeni dosyadan grup yazma bitini kaldırır. Sonuç olarak dosyalar 0644 izinleriyle oluşturulur ve yapılandırdığınız paylaşım işlevsiz kalır. 002 ayarı 0664 dosyalar ve 0775 dizinler oluşturur; böylece grup yazma yetkisine sahip olur:
services:
sonarr:
image: lscr.io/linuxserver/sonarr:latest
container_name: sonarr
environment:
- PUID=${PUID}
- PGID=${PGID}
- UMASK=002
- TZ=Etc/UTC
volumes:
- /srv/appdata/sonarr:/config
- /srv/media:/data
restart: unless-stoppedBu iki değer, Compose dosyasının yanındaki bir .env dosyasında bulunmalıdır; böylece tüm yığın tek bir tanımı okur:
PUID=1000
PGID=13000Compose, kimlik bilgileri için kullandığınız mekanizmanın aynısı olan ${PUID} tarzı değişken değişimi için bu dosyayı otomatik olarak okur. Değerleri docker-compose.yml dosyasından ayrı tutup bir .env dosyasında tutma alışkanlıkları burada da geçerlidir; tek fark, bu iki sayının gizli bilgi olmamasıdır.
Yapılandırmaya güvenmek yerine uçtan uca doğrulama yapın. Bir container'ın içinden bir dosya yazın ve ana makineden okuyun:
docker exec sonarr touch /data/downloads/permtest
ls -ln /srv/media/downloads/permtestSağlıklı bir sonuç; PUID değerinizi sahibi, 13000 değerini grup ve -rw-rw-r-- değerini mod olarak göstermelidir. Eğer grup 1000 olarak görünüyorsa, dizinde setgid biti eksiktir. Eğer mod -rw-r--r-- olarak görünüyorsa, UMASK değişkeni etkili olmamıştır; bu durumda container'ı yeniden başlatmak yerine yeniden oluşturduğunuzdan emin olun. İşiniz bittiğinde test dosyasını rm /srv/media/downloads/permtest ile silin.
Hangi imajın hangi değişkeni kullandığı
linuxserver.io imajları PUID, PGID ve UMASK kullanır. Paperless-ngx aynı mantık için farklı isimler kullanır: USERMAP_UID ve USERMAP_GID; her ikisi de varsayılan olarak 1000 değerini alır ve dokümantasyonu bunları id -u ve id -g üzerinden okumanızı önerir. Fotoğraf sunucuları da benzer bir çeşitlilik gösterir: PhotoPrism kendi PHOTOPRISM_UID ve PHOTOPRISM_GID ikilisine sahipken, Immich herhangi bir eşdeğer sunmaz ve container kullanıcısını Docker'ın user: anahtarına bırakır; bu nedenle PhotoPrism ile Immich arasında seçim yapmak, sunucudaki en büyük kütüphane için bu mekanizmalardan hangisini yönetmeniz gerektiğini de belirler. Yaygın veritabanı ve web sunucusu imajları dahil olmak üzere birçok resmi upstream imajı, sabit bir yerleşik kullanıcı ile gelir ve sizden user: kullanmanızı veya ayarı olduğu gibi bırakmanızı bekler. Aynı durum daha sonra eklediğiniz altyapı bileşenleri için de geçerlidir; bu yüzden tek bir giriş için uygulamalarınızın önüne Authentik koymak, PUID okumayan resmi sunucu, Postgres ve Redis imajlarını çalıştırmak anlamına gelir ve bu imajlarda dosya sahipliği, yapılandırabileceğiniz bir entrypoint yerine çalışma zamanında belirlenir.
Bu nedenle, projeler arasında bir environment bloğunu kopyalamadan önce her imajın README dosyasını kontrol edin. Docker, ayarladığınız tüm ortam değişkenlerini, içerideki bir uygulama bunları okusa da okumasa da container içine aktarır; hiçbir şeyin tüketmediği bir PUID değişkeni hata veya uyarı üretmez, hiçbir etki de yaratmaz. Container, kendi Dockerfile dosyasının sonunda tanımlanan kullanıcı ile çalışır; bunu da yazdığı dosyaların sahiplik bilgilerinden anlayabilirsiniz.
FAQ
Docker dosyalarımın sahibi neden 911:911 olarak görünüyor?
911, linuxserver.io imajlarının içine gömülü olan abc kullanıcısının UID ve GID değeridir. Bu değerin görülmesi, container'ın PUID ve PGID değişkenleri ayarlanmadan başlatıldığını ve bu nedenle init betiğinin varsayılan değerleri koruduğunu gösterir. ls -l, ana makinenizde 911 ID'sine sahip bir hesap bulunmadığı için isim yerine ham sayıları görüntüler. PUID ve PGID değişkenlerini id komutunun çıktısına göre ayarlayın, container'ı docker compose up -d ile yeniden oluşturun ve ardından etkilenen dizin üzerinde sudo chown -R 1000:1000 komutuyla mevcut dosyaların sahipliğini düzeltin.
PUID ve PGID her Docker imajında çalışır mı?
Hayır. Bunlar bir Docker özelliği değildir ve Docker tarafından okunmazlar. Yalnızca kendi giriş noktası (entrypoint) bu değişkenleri okuyan ve uygulamayı başlatmadan önce usermod ve groupmod komutlarını çalıştıran imajlarda işe yararlar; linuxserver.io ailesi ve bu yapıyı kopyalayan birkaç proje buna örnektir. Diğer projeler, paperless-ngx içindeki USERMAP_UID ve USERMAP_GID gibi farklı isimler kullanır. Bu değişkenlerin hiçbirini okumayan bir imajda, değişkenler kabul edilir ancak hiçbir uyarı verilmeden göz ardı edilir.
Docker Compose içinde PUID ve PGID mi yoksa user: anahtarı mı kullanmalıyım?
İmaj destekliyorsa PUID ve PGID kullanın; çünkü giriş noktası, /config dizinini düzeltmek ve kendi servislerini doğru şekilde başlatmak için yeterli süre boyunca root yetkisiyle çalışmaya devam eder. İmajın PUID desteği yoksa veya imajın README dosyasında root olmayan kullanıcıyla çalışmak üzere test edildiği belirtilmişse user: kullanın. Bir linuxserver imajında user: ayarını yapmak, PUID ve PGID değişkenlerini etkisiz hale getirir, Docker Mods ve özel servislerin çalışmasını durdurur; ayrıca tüm mount edilmiş birimlerin izin sorumluluğunu tamamen size yükler.
Sonarr doğru PUID değerine sahip olmasına rağmen dosyaları taşıyamıyor. Sorun nedir?
Sırasıyla üç noktayı kontrol edin. Birincisi, medya mount işleminin kendisi: init betiği yalnızca /app, /config ve /defaults dizinlerinde chown işlemi yapar; bu nedenle /data veya /downloads dizinleri, ana makinedeki sahiplik bilgilerini korur. İkincisi, paylaşılan grup: eğer indirme istemcisi ve Sonarr farklı GID değerleri altında çalışıyorsa, hiçbiri diğerinin dosyalarını değiştiremez; bu yüzden stack içindeki tüm container'lara aynı PGID değerini verin. Üçüncüsü, umask: imajın varsayılan UMASK=022 değeri, dosyaları grup yazma biti olmadan 0644 şeklinde yazar ve bu durum paylaşılan grup mantığını tamamen bozar. UMASK=002 ayarını yapın ve yeni dosyaların grubu devralması için dizinlerde chmod 2775 ile setgid bitini aktif hale getirin.