Docker Compose में PUID और PGID का सही उपयोग कैसे करें
PUID और PGID Docker की सेटिंग्स नहीं हैं बल्कि linuxserver.io इमेज की एक परंपरा है। जानें कि क्यों आपकी फाइलें 911:911 ओनरशिप के साथ सेव होती हैं और इन्हें कैसे ठीक करें।
PUID और PGID वास्तव में क्या हैं
PUID और PGID दो environment variables हैं जिन्हें कुछ container images startup के समय पढ़ती हैं। Docker स्वयं इन्हें कभी नहीं देखता। ये एक convention हैं, जिनका उपयोग linuxserver.io images और कुछ अन्य द्वारा किया जाता है, इसलिए जो image इन्हें पढ़ने के लिए नहीं लिखी गई है, वह इन्हें चुपचाप अनदेखा कर देती है।
एक linuxserver.io image के अंदर abc नाम का एक user होता है, जिसे build के समय UID (user ID) 911 और GID (group ID) 911 के साथ बनाया जाता है। Container root के रूप में start होता है, अपनी init scripts चलाता है, और उन scripts में से एक application शुरू होने से पहले उस user को renumber कर देती है:
groupmod -o -g "${PGID}" abc
usermod -o -u "${PUID}" abc-o flag ऐसी ID का उपयोग करने की अनुमति देता है जो पहले से कहीं और उपयोग में है। उसके बाद init privileges को छोड़ देता है और application को abc के रूप में चलाता है। इसलिए Docker किसी अन्य environment variable की तरह PUID=1000 को container में pass करता है और इस पर कभी कोई कार्रवाई नहीं करता। यह variable application शुरू होने से पहले container के अंदर एक user को renumber करता है, जिसका अर्थ है कि user namespace remapping के बिना एक standard rootful daemon पर, नई बनाई गई फाइलें सामान्यतः आपके disk पर 1000 के स्वामित्व में होती हैं। किसी मौजूदा writable file को लिखने से उसका owner नहीं बदलता है। Rootless Docker उस number को shift कर देता है, जैसा कि नीचे विस्तार से समझाया गया है। PUID को unset छोड़ दें और abc 911 ही रहता है, यही कारण है कि एक unconfigured bind mount उन फाइलों से भर जाता है जिनका owner 911:911 होता है।
id के साथ अपने दो numbers प्राप्त करें
इसे host पर उस user के रूप में चलाएं जो data directories का स्वामी है:
iduid=1000(deploy) gid=1000(deploy) groups=1000(deploy),27(sudo),988(docker)uid आपका PUID है और gid आपका PGID है। किसी script के लिए, id -u और id -g केवल numbers को print करते हैं। अधिकांश नए VPS images पर पहला human account 1000:1000 होता है, लेकिन इसे मानकर न चलें। आवंटन मौजूद accounts और configuration पर निर्भर करता है: एक rebuilt server फिर से 1000 आवंटित कर सकता है, जबकि बाद वाले account को उच्च उपलब्ध ID मिलती है। यदि आपकी services अपने login user के बजाय एक dedicated service account के अंतर्गत चलती हैं, तो id thatuser चलाएं और वहां से numbers लें।
आपकी फाइलें 911:911 के रूप में क्यों दिखाई देती हैं
ls -l एक संख्यात्मक ID प्रिंट करता है, न कि नाम, जब उस ID से कोई host account मेल नहीं खाता। यदि UID 911 से कोई host account मेल नहीं खाता है, तो प्रिंट करने के लिए कोई नाम नहीं होता। हर बार संख्याएँ देखने और अस्पष्टता को दूर करने के लिए ls -ln का उपयोग करें:
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.xmlवह आउटपुट container के इन-बिल्ट डिफॉल्ट्स से मेल खाता है, लेकिन केवल मौजूदा फाइलें यह साबित नहीं करतीं कि application वर्तमान में किस user के रूप में चल रही है। उस लिस्टिंग में config.xml वह फाइल भी है जिसमें authentication सेटिंग्स होती हैं, जो तब महत्वपूर्ण हो जाती है जब आप पहली बार web UI खोलते हैं और पाते हैं कि Sonarr और Radarr बिना किसी डिफॉल्ट username या password के आते हैं। अनुमान लगाने के बजाय container के अंदर से इसकी पुष्टि करें:
docker exec sonarr id abc
docker compose logs sonarr | head -n 25linuxserver init अपने परिणाम को startup log में दो लाइनों के रूप में प्रिंट करता है:
User UID: 911
User GID: 911यदि आपके Compose फाइल में PUID=1000 सेट करने के बाद भी वे लाइनें 911 पढ़ती हैं, तो चल रहा container आपके द्वारा सेट किए गए मान का उपयोग नहीं कर रहा है। इसका सामान्य कारण यह है कि आपने docker-compose.yml को एडिट किया और फिर docker compose restart चलाया, जो मौजूदा container को उसके मूल environment के साथ फिर से उपयोग करता है। Environment परिवर्तनों के लिए docker compose up -d की आवश्यकता होती है, जो container को फिर से बनाता है। दूसरा कारण जानबूझकर किया गया होता है: जब कोई image अपने read-only या non-root मोड में चलती है, तो init renumbering को पूरी तरह से छोड़ देता है, भले ही variable container में मौजूद हो। Read-only मोड में banner abc की अपरिवर्तित ID की रिपोर्ट करता है; non-root मोड में यह /run के मालिक की रिपोर्ट करता है।
कंटेनर द्वारा लिखी गई फाइल को आप डिलीट क्यों नहीं कर सकते
कर्नेल नामों की तुलना नहीं करता, केवल संख्याओं की तुलना करता है। आपका शेल UID 1000 के रूप में चलता है। फाइल UID 911 की है। इसे रखने वाली डायरेक्टरी drwxr-xr-x है और वह भी 911 की है, इसलिए ग्रुप और अन्य को पढ़ने और निष्पादित करने (read and execute) की अनुमति तो है, लेकिन लिखने (write) की नहीं। किसी फाइल को डिलीट करने के लिए उसकी डायरेक्टरी पर राइट परमिशन की आवश्यकता होती है, न कि फाइल पर, इसलिए फाइल के सामान्य दिखने पर भी आपको यह त्रुटि मिलती है:
rm: cannot remove '/srv/appdata/sonarr/config.xml': Permission deniedएक राइटिंग कंटेनर दूसरी तरफ से इसी बाधा का सामना करता है। यदि होस्ट डायरेक्टरी आपके यूजर की है और उसका मोड 755 है, और एप्लिकेशन 911 के रूप में चलता है, तो उसका पहला राइट ऑपरेशन Permission denied के साथ विफल हो जाता है और एप्लिकेशन इसे अपने शब्दों में रिपोर्ट करता है। Sonarr या Radarr जैसे .NET एप्लिकेशन में यह UnauthorizedAccessException: Access to the path '/data/downloads' is denied के रूप में दिखाई देता है। फाइल के सामने मौजूद परमिशन स्ट्रिंग आपको बताती है कि तीन परमिशन सेट में से कौन सा वास्तव में आप पर लागू हो रहा है, और drwxr-xr-x को सही ढंग से पढ़ना ही वह तरीका है जिससे यह त्रुटि रहस्यमय के बजाय स्पष्ट हो जाती है।
यह विशेष रूप से bind mount की समस्या है। जब Docker एक empty named volume बनाता है और उसे इमेज में मौजूद पाथ पर माउंट करता है, तो वह उस पाथ की सामग्री को वॉल्यूम में कॉपी कर देता है, जिसमें ओनरशिप और परमिशन बिट्स भी शामिल होते हैं, ताकि एप्लिकेशन को वह डायरेक्टरी मिल जाए जिसका वह पहले से मालिक है। Bind mount के साथ ऐसा कुछ नहीं होता: Docker आपकी होस्ट डायरेक्टरी को बिल्कुल वैसा ही माउंट करता है जैसी वह है। यह अंतर उन व्यावहारिक कारणों में से एक है जिनके लिए यह जानना जरूरी है कि bind mount कब named volume से बेहतर होता है और कब नहीं।
ऐसी डायरेक्टरी को ठीक करना जो पहले से ही गलत है
PUID और PGID सेट करने से एप्लिकेशन का भविष्य का व्यवहार बदल जाता है। यह डिस्क पर मौजूद हर फाइल को पूर्वव्यापी रूप से ठीक नहीं करता है, हालाँकि init नीचे वर्णित विशिष्ट पाथ्स पर ओनरशिप को सही कर देता है। स्टैक को रोकें, ओनरशिप को स्वयं ठीक करें, और फिर इसे दोबारा शुरू करें:
docker compose down
sudo chown -R 1000:1000 /srv/appdata/sonarr
docker compose up -dयदि आप नंबर टाइप नहीं करना चाहते हैं तो sudo chown -R "$(id -u):$(id -g)" /srv/appdata/sonarr का उपयोग करें। इसे कंटेनर को रोककर करें, क्योंकि एक रनिंग एप्लिकेशन जो रिकर्सिव chown के दौरान बीच में लिख रही हो, वह एक आधी-अधूरी ठीक की गई डायरेक्टरी ट्री और त्रुटियों के एक भ्रमित करने वाले दूसरे दौर के साथ समाप्त हो सकती है।
PUID और PGID से जो समस्याएँ हल नहीं होतीं
यह वह हिस्सा है जहाँ वे लोग फंस जाते हैं जिन्होंने बाकी सब कुछ सही किया होता है। linuxserver बेस इमेज की user setup स्क्रिप्ट स्टार्टअप पर तीन paths को chown करती है: /app, /config और /defaults। आपके मीडिया mounts इस सूची में नहीं होते हैं। /data, /downloads और /tv को एप्लिकेशन तक बिना किसी बदलाव के पहुँचाया जाता है। इसलिए, यदि उन mounts के host साइड पर ऐसी ओनरशिप है जिसे container यूजर एक्सेस नहीं कर सकता, तो container सही तरीके से स्टार्ट हो जाएगा, अपने बैनर में सही UID दिखाएगा, लेकिन पहली बार फाइल इम्पोर्ट करते ही फेल हो जाएगा।
यह सही व्यवहार है। हर बार container स्टार्ट होने पर बारह टेराबाइट की मीडिया लाइब्रेरी पर रिकर्सिव chown चलाना एक आपदा होगी। इसका मतलब यह है कि मीडिया डायरेक्टरीज की जिम्मेदारी आपकी है, और यही वे mounts हैं जहाँ अनुमतियों (permissions) में वास्तव में गड़बड़ी होती है। चूँकि इस तरह की विफलता एप्लिकेशन लॉग में container के स्वस्थ दिखने के घंटों बाद चुपचाप सामने आती है, इसलिए अपने VPS पर ntfy का उपयोग करके, फोन पर अलर्ट भेजने के लिए एक आवधिक राइट टेस्ट (write test) सेट करना एक सस्ता तरीका है, जिससे आपको एक हफ्ते तक एपिसोड मिस होने से पहले ही इसकी जानकारी मिल जाएगी।
उपयोगकर्ता को नियंत्रित करने के तीन तरीके, और प्रत्येक कब लागू होता है
PUID और PGID environment variables
यह केवल उन images पर काम करता है जिनका entrypoint इन्हें पढ़ता है। यह लोकप्रिय है क्योंकि container अभी भी root के रूप में start होता है, अपना setup खुद करता है, /config को ठीक करता है, और उसके बाद ही privileges को कम करता है। Docker Mods और custom init scripts काम करते रहते हैं। इसकी कीमत यह है कि आप एक platform feature के बजाय एक convention पर भरोसा कर रहे हैं, और variable के नाम सभी projects में एक समान नहीं होते हैं।
Compose में user: key
यह एक वास्तविक Docker feature है और हर image पर काम करता है, क्योंकि container runtime इसे image के अपने code के चलने से पहले लागू कर देता है:
services:
sonarr:
image: lscr.io/linuxserver/sonarr:latest
user: "1000:1000"process कभी भी root के रूप में नहीं चलती, एक पल के लिए भी नहीं, जो कि एक वास्तविक security लाभ है। यह entrypoint में मौजूद किसी भी ऐसी चीज़ को भी तोड़ देता है जिसे root की आवश्यकता थी। linuxserver images पर, project उचित प्रयासों के आधार पर और केवल उन images के लिए इसका समर्थन करता है जिनका उसने परीक्षण किया है, और इसकी शर्तें विशिष्ट हैं: PUID और PGID का कोई प्रभाव नहीं रहता, Docker Mods नहीं चलेंगे, custom services नहीं चलेंगी, और आप हर mounted volume की permissions के लिए जिम्मेदार हो जाते हैं। उनका प्रलेखित pattern इस flag को एक writable /run के साथ जोड़ता है:
user: 1000:1000
tmpfs:
- /run:uid=1000,gid=1000,exec
security_opt:
- no-new-privileges=trueएक cosmetic side effect लोगों को हैरान करता है। एक numeric user: जिसका container के /etc/passwd में कोई मेल खाने वाला entry नहीं है, वह tools के अंदर whoami: cannot find name for user ID 1000 रिपोर्ट करता है। ID वैध है और file access सामान्य रूप से काम करता है। केवल नाम का lookup विफल रहता है।
Rootless Docker
Rootless Docker daemon को आपके unprivileged user के रूप में चलाता है, इसलिए daemon और containers host root privileges के बिना चलते हैं। यह ownership के गणित को पूरी तरह से बदल देता है। Container UID 0, rootless Docker चलाने वाले user के host UID पर map होता है, और 1 या उससे अधिक के किसी भी n के लिए container UID n, subuid + (n - 1) पर map होता है, जहाँ subuid वह range का आधार है जो आपको /etc/subuid में आवंटित की गई है; group IDs भी /etc/subgid का उपयोग करके उसी नियम का पालन करते हैं। Docker वहाँ कम से कम 65,536 subordinate IDs की अपेक्षा करता है।
उस mapping को फिर से पढ़ें, क्योंकि यह सामान्य सलाह को उलट देता है। Rootless Docker के तहत, root के रूप में file बनाने वाला container सामान्य रूप से आपके स्वामित्व वाली file बनाता है। UID 1000 के रूप में file बनाने वाला container सामान्य रूप से एक subordinate ID वाली file बनाता है, जैसे कि 100999 जब range 100000 से शुरू होती है। आपके shell का access permissions और ACLs पर निर्भर करता है; deletion सामान्य रूप से containing directory पर निर्भर करता है, इसलिए आप उस file को उस directory से delete कर सकते हैं जिसे आप नियंत्रित करते हैं। इसलिए, rootful daemon पर जो PUID value सही है, वह यहाँ गलत है। ये दोनों तंत्र अलग-अलग layers पर ownership बदलते हैं, और जाँच किए बिना उन्हें एक साथ इस्तेमाल करने से आप mounted data में write करने में असमर्थ हो सकते हैं। यदि आप rootless का उपयोग करते हैं, तो library को migrate करने से पहले अपने सर्वर पर एक लिखी गई file की ownership का परीक्षण करें।
एक ही VPS पर अधिकांश self-hosted stacks के लिए, rootful daemon पर PUID और PGID का उपयोग करना व्यावहारिक विकल्प है, क्योंकि images इसी के लिए बनाई और प्रलेखित की गई हैं। user: का उपयोग तब करें जब image README में कहा गया हो कि उस image का इसके लिए परीक्षण किया गया है, या जब आप कोई आधिकारिक upstream image चला रहे हों जिसमें PUID का कोई समर्थन नहीं है। एक VPS पर self-hosted AFFiNE instance जैसा document workspace इस अंतिम मामले में आता है, क्योंकि इसका कोई भी container PUID नहीं पढ़ता है और इसकी database directory और uploaded files की ownership environment block में किसी चीज़ के बजाय runtime द्वारा तय की जाती है। यही बात एक self-hosted Chatwoot support desk पर भी लागू होती है, जहाँ Rails container और उसका Sidekiq worker दोनों एक uploads directory में write करते हैं और उनमें से कोई भी PUID नहीं पढ़ता है, इसलिए उस directory को उसी user से मेल खाना चाहिए जिसके रूप में image पहले से चल रही है। किसी नए stack के लिए भी इसमें से कुछ नहीं बदलता है, इसलिए टीम के हर व्यक्ति को अपना sandboxed OneCLI agent देना per-person workspace directories और Postgres data directory को उस user के स्वामित्व में छोड़ देता है जिसके रूप में प्रत्येक image पहले से चलती है, जो इसे PUID समस्या के बजाय एक user: और chown समस्या बनाता है। Codex, Claude Code और Hermes के सामने एक single self-hosted API रखें और इसका entrypoint कई identities को प्रबंधित करता है: container को root के रूप में start होना चाहिए, console और gateway एक unprivileged user के रूप में चलते हैं, और प्रत्येक agent session अपने स्वयं के user के रूप में चलता है। उस deployment में user: न जोड़ें; इसका entrypoint data volume की ownership को संभालता है।
मीडिया स्टैक का मामला: कंटेनरों के बीच साझा किया गया एक ग्रुप
एक Sonarr, Radarr और डाउनलोड क्लाइंट वाला arr मीडिया स्टैक वह जगह है जहाँ यह सिद्धांत केवल थ्योरी नहीं रह जाता। डाउनलोड क्लाइंट एक पूरी हो चुकी फाइल को /data/downloads में लिखता है। इसके बाद Sonarr उस फाइल को /data/media में हार्डलिंक या मूव करता है। हार्डलिंक के काम करने के लिए दोनों कंटेनरों को एक ही ट्री (tree) पर राइट एक्सेस की आवश्यकता होती है। यदि डाउनलोड क्लाइंट 1000 के रूप में चलता है और Sonarr 1001 के रूप में, और उनके पास साझा ग्रुप राइट परमिशन नहीं है, तो उनमें से एक के पास ऐसी फाइलें होंगी जिन्हें दूसरा केवल पढ़ सकता है।
इसका समाधान एक साझा ग्रुप है जिसे स्टैक का प्रत्येक कंटेनर अपने PGID के रूप में उपयोग करता है:
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 में शुरुआती 2, setgid बिट है। एक डायरेक्टरी पर इसका अर्थ है कि इसके अंदर बनाई गई प्रत्येक नई फाइल और सब-डायरेक्टरी, निर्माता के प्राथमिक ग्रुप के बजाय ग्रुप media को इनहेरिट (inherit) करती है। इस प्रकार, आपको बार-बार chown चलाने की आवश्यकता नहीं पड़ती और यह व्यवस्था नए डाउनलोड के साथ भी बनी रहती है। अपने एक्सेस की जाँच करने से पहले लॉग आउट करके पुनः लॉग इन करें, या newgrp media चलाएँ: usermod -aG के साथ जोड़ा गया ग्रुप पहले से खुले शेल सेशन में दिखाई नहीं देता है।
कंटेनर के अंदर, groupmod -o -g 13000 abc, abc ग्रुप को 13000 पर री-नंबर करता है, ताकि abc उसी GID के साथ लिखे जो आपके होस्ट media ग्रुप का है। प्रत्येक linuxserver कंटेनर जो इस ट्री को एक्सेस करता है, अपना PUID बनाए रखता है और उस एक PGID को साझा करता है। इसमें वे कंटेनर भी शामिल हैं जो चेन में आगे हैं और केवल तैयार लाइब्रेरी को पढ़ते हैं, जैसे कि स्वयं Jellyfin। Halcyon, जो उस लाइब्रेरी को 90 के दशक के वीडियो स्टोर की तरह दिखाता है, जैसा फ्रंट एंड, HALCYON_JELLYFIN_URL का उपयोग करके HTTP पर Jellyfin से जुड़ता है; इसके स्टैंडर्ड डिप्लॉयमेंट को न तो साझा मीडिया PGID की आवश्यकता होती है और न ही मीडिया-डायरेक्टरी माउंट की।
इसके बाद स्टैक के प्रत्येक linuxserver कंटेनर पर UMASK=002 सेट करें। यह वह चरण है जिसे लोग भूल जाते हैं। यदि इसे सेट न किया जाए, तो एप्लिकेशन अपने इनहेरिट किए गए umask को बनाए रखता है जब तक कि कोई अन्य चीज़ इसे बदल न दे, और इमेज READMEs में दिखाया गया उदाहरण मान UMASK=022 है। 022 के प्रभावी umask के साथ, एक नई फाइल के लिए 0666 का अनुरोध करने वाला एप्लिकेशन 0644 प्राप्त करता है जब कोई डिफ़ॉल्ट ACL नहीं होता है: ग्रुप के बाकी सदस्य इसे पढ़ तो सकते हैं लेकिन बदल नहीं सकते, जो आपके द्वारा कॉन्फ़िगर की गई अधिकांश शेयरिंग को निष्प्रभावी कर देता है। 002 और बिना किसी डिफ़ॉल्ट ACL के, एक एप्लिकेशन जो फाइलों के लिए सामान्य 0666 और डायरेक्टरी के लिए 0777 का अनुरोध करता है, उसे 0664 फाइलें और, setgid ट्री के अंदर, 2775 डायरेक्टरी मिलती हैं, और ग्रुप राइट कर सकता है। umask केवल बिट्स को हटाता है, इसलिए जो एप्लिकेशन 0600 मांगता है उसे अभी भी 0600 मिलता है, और डिफ़ॉल्ट ACL वाली डायरेक्टरी umask को पूरी तरह से अनदेखा कर देती है। PUID और PGID के साथ वेरिएबल जोड़ें:
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-stoppedये दो मान Compose फाइल के बगल में एक .env फाइल में होने चाहिए, ताकि पूरा स्टैक एक ही परिभाषा पढ़े:
PUID=1000
PGID=13000Compose ${PUID} स्टाइल सब्स्टीट्यूशन के लिए उस फाइल को स्वचालित रूप से पढ़ता है, जो वही मैकेनिज्म है जिसका उपयोग आप क्रेडेंशियल्स के लिए करते हैं। docker-compose.yml से मानों को बाहर रखकर .env फाइल में रखने की आदतें यहाँ भी लागू होती हैं, अंतर केवल इतना है कि ये दो नंबर गुप्त नहीं हैं।
कॉन्फ़िगरेशन पर भरोसा करने के बजाय इसे शुरू से अंत तक सत्यापित करें। एप्लिकेशन के यूजर के रूप में एक नई फाइल लिखें, कॉन्फ़िगर किया गया umask लागू करें, और इसे होस्ट से पढ़ें। एक ऐसे टेस्ट फाइलनेम का उपयोग करें जो पहले से मौजूद न हो:
docker exec --user abc sonarr sh -c 'umask "$UMASK" && touch /data/downloads/permtest'
ls -ln /srv/media/downloads/permtestएक सही परिणाम में आपका PUID मालिक के रूप में, 13000 ग्रुप के रूप में, और -rw-rw-r-- मोड के रूप में दिखाई देगा। यदि ग्रुप 1000 पढ़ता है, तो ls -ldn /srv/media/downloads चलाएँ: या तो उस डायरेक्टरी से setgid बिट (drwxrwsr-x में s) गायब है, या डायरेक्टरी स्वयं media के बजाय ग्रुप 1000 की है, और ऊपर दिए गए chown और chmod 2775 कमांड दोनों को ठीक कर देंगे। यदि मोड -rw-r--r-- पढ़ता है, तो कंटेनर के UMASK मान और डायरेक्टरी के डिफ़ॉल्ट ACL की जाँच करें; यदि इसका एनवायरनमेंट पुराना है तो कंटेनर को पुनः बनाएँ। यह टेस्ट कॉन्फ़िगर किए गए मास्क के साथ abc के रूप में निर्माण की जाँच करता है; एप्लिकेशन का अपना निर्माण मोड और प्रभावी umask अभी भी उसकी फाइलों को निर्धारित करते हैं। काम पूरा होने पर rm /srv/media/downloads/permtest के साथ टेस्ट फाइल को हटा दें।
कौन सी images किन variables का उपयोग करती हैं
linuxserver.io images PUID, PGID और UMASK का उपयोग करती हैं। Paperless-ngx इसी विचार के लिए अलग नामों का उपयोग करता है: USERMAP_UID और USERMAP_GID, जो दोनों डिफ़ॉल्ट रूप से 1000 पर सेट होते हैं, और इसका documentation आपको इन्हें id -u और id -g से पढ़ने के लिए कहता है। Photo servers में भी यही विविधता देखने को मिलती है: PhotoPrism का अपना PHOTOPRISM_UID और PHOTOPRISM_GID का जोड़ा है, जबकि Immich कोई समकक्ष विकल्प नहीं देता और container user को Docker की user: key पर छोड़ देता है, इसलिए PhotoPrism और Immich के बीच चयन यह भी तय करता है कि आप सर्वर पर मौजूद सबसे बड़ी लाइब्रेरी के लिए इनमें से कौन सा mechanism maintain करेंगे। कई आधिकारिक upstream images, जिनमें सामान्य database और web server images शामिल हैं, एक fixed built-in user के साथ आती हैं और आपसे अपेक्षा करती हैं कि आप user: का उपयोग करें या उसे वैसा ही रहने दें। छोटे single-app deployments में भी यही सवाल उठता है, इसलिए जब आप self-hosted openGym workout tracker सेटअप करते हैं, तो bind mount को point करने से पहले यह जाँच लेना उचित है कि उसका container वास्तव में किस user के रूप में चलता है, क्योंकि उसके database वाली directory उसी user की पहचान अपना लेती है, चाहे आपने PUID सेट किया हो या नहीं। एक remote access relay भी इसी श्रेणी में आता है, इसलिए जब आप अपना खुद का RustDesk relay server चलाते हैं, तो hbbs द्वारा पहली बार start होने पर जो Ed25519 key pair लिखा जाता है, वह आपके bind mount में उस user के स्वामित्व में आता है जिसके साथ वह image समाप्त हुई। आप बाद में host side पर chown के साथ इसे ठीक कर सकते हैं, या user: key के साथ पहले ही identity चुन सकते हैं, क्योंकि वह image अपना कोई user सेट नहीं करती, बशर्ते कि mounted directory आपके द्वारा चुने गए ID के लिए writable हो। यही बात बाद में जोड़ी गई infrastructure पर भी लागू होती है, इसलिए single login के लिए अपने apps के सामने Authentik रखना का मतलब है आधिकारिक authentik और Postgres images चलाना जो PUID को बिल्कुल नहीं पढ़ती हैं, और उनके volume का स्वामित्व उन users से आता है जिनके रूप में उनकी processes चलती हैं और जो setup उनके entrypoints द्वारा किया जाता है। Authentik ने release 2025.10 में अपनी Redis dependency हटा दी है।
इसलिए projects के बीच environment block कॉपी करने से पहले प्रत्येक image का README देखें। Docker आपके द्वारा सेट की गई किसी भी environment variable को container में भेज देता है, चाहे अंदर की कोई चीज़ उसे पढ़े या न पढ़े, और एक ऐसी PUID जिसका उपयोग कोई नहीं करता, वह न तो कोई error देती है, न warning और न ही उसका कोई प्रभाव पड़ता है। Container Docker की user: setting या Dockerfile द्वारा चुने गए user के रूप में start होता है, और उसका entrypoint application start करने से पहले privileges को कम (drop) कर सकता है। बॉक्स में कुछ भी नया जोड़ने से पहले यह जानकारी जरूर पढ़ें, जिसमें self-hosted open-kritt security scanning stack भी शामिल है, जहाँ Compose file आपको बताती है कि क्या images PUID का सम्मान करती हैं या आपके द्वारा mount की गई directories का स्वामित्व images द्वारा ही fixed किया गया है।
FAQ
मेरे Docker files का owner 911:911 क्यों है?
911, linuxserver.io images में इनबिल्ट abc user का UID और GID है। यह इनबिल्ट defaults से मेल खाता है, लेकिन container का PUID और PGID बदलने के बाद भी files पर वही ownership बनी रह सकती है। जब आपके host पर कोई account उन IDs से मेल नहीं खाता, तो ls -l raw numbers दिखाता है क्योंकि प्रदर्शित करने के लिए कोई नाम नहीं होता। PUID और PGID को id के आउटपुट पर सेट करें, docker compose up -d के साथ container को recreate करें, और फिर प्रभावित directory पर sudo chown -R 1000:1000 चलाकर existing files को ठीक करें।
क्या PUID और PGID हर Docker image पर काम करते हैं?
नहीं। ये Docker का feature नहीं हैं और Docker इन्हें कभी नहीं पढ़ता। ये केवल उन images पर काम करते हैं जिनका entrypoint इन्हें पढ़ता है और application शुरू करने से पहले usermod और groupmod को कॉल करता है। यह linuxserver.io family और इस पैटर्न को कॉपी करने वाले कुछ प्रोजेक्ट्स में होता है। अन्य प्रोजेक्ट्स अलग नाम इस्तेमाल करते हैं, जैसे paperless-ngx में USERMAP_UID और USERMAP_GID। ऐसी image पर जो इनमें से किसी को नहीं पढ़ती, variables स्वीकार कर लिए जाते हैं लेकिन बिना किसी चेतावनी के ignore कर दिए जाते हैं।
क्या मुझे Docker Compose में PUID और PGID का उपयोग करना चाहिए या user: key का?
जब image उन्हें सपोर्ट करती हो तो PUID और PGID का उपयोग करें, क्योंकि entrypoint /config को ठीक करने और अपनी services को सही ढंग से शुरू करने के लिए पर्याप्त समय तक root के रूप में चलता है। जब image चुने गए user के लिए सपोर्ट का दस्तावेजीकरण (document) करती हो, तब user: का उपयोग करें; केवल PUID सपोर्ट न होने का मतलब यह नहीं है कि उसका entrypoint बिना root के काम करता है। linuxserver image पर, user: सेट करने से PUID और PGID निष्क्रिय हो जाते हैं, Docker Mods और custom services का चलना बंद हो जाता है, और हर mounted volume की permissions की जिम्मेदारी आपकी हो जाती है।
Sonarr के पास सही PUID है लेकिन फिर भी वह files move नहीं कर पा रहा है। क्या गलत है?
क्रमवार तीन चीजों की जाँच करें। पहला, media mount स्वयं: base image की user setup script /app, /config और /defaults को chown करती है, इसलिए /data या /downloads पर host वाली ownership ही बनी रहती है। दूसरा, shared group: media tree को access करने वाले containers को समान PGID और group write permissions दें। तीसरा, umask: जब application 0666 का अनुरोध करती है और कोई default ACL लागू नहीं होता, तो 022 का प्रभावी मास्क 0644 files बनाता है, जिससे group के अन्य containers उन्हें पढ़ तो सकते हैं लेकिन modify नहीं कर सकते। UMASK को unset छोड़ने से किसी विशेष मास्क या file mode की गारंटी नहीं मिलती। UMASK=002 सेट करें और chmod 2775 के साथ directories पर setgid bit सेट करें ताकि नई files group को inherit कर सकें। 0600 का अनुरोध करने वाली application अभी भी private files बनाती है, और एक default ACL यह बदल देता है कि creation permissions कैसे असाइन की जाती हैं।