Docker Compose मध्ये PUID आणि PGID काय करतात?
PUID आणि PGID ही Docker settings नाहीत, तर linuxserver.io images मधील entrypoint convention आहे. bind mount मधील files 911:911 का होतात आणि ते कसे दुरुस्त करायचे ते जाणून घ्या.
PUID आणि PGID प्रत्यक्षात काय आहेत
PUID आणि PGID हे दोन environment variables आहेत. काही container images startup वेळी त्यांची मूल्ये वाचतात. Docker स्वतः ही variables तपासत नाही. ही linuxserver.io images आणि इतर काही images मध्ये वापरली जाणारी convention आहे. त्यामुळे ती वाचण्यासाठी तयार न केलेली image या variables कडे दुर्लक्ष करते आणि कोणतीही सूचना देत नाही.
linuxserver.io image मध्ये abc नावाचा user असतो. तो build वेळी UID (user ID) 911 आणि GID (group ID) 911 सह तयार केला जातो. Container root म्हणून सुरू होतो आणि त्याच्या init scripts चालवतो. या scripts पैकी एक script इतर कोणतीही प्रक्रिया सुरू होण्यापूर्वी त्या user चे IDs बदलतो:
groupmod -o -g "${PGID}" abc
usermod -o -u "${PUID}" abc-o flag मुळे आधीच इतरत्र वापरात असलेला ID वापरता येतो. त्यानंतर init privileges कमी करतो आणि application abc म्हणून चालवतो. त्यामुळे PUID=1000 Docker पर्यंत पोहोचत नाही. Application सुरू होण्यापूर्वी ही variable container मधील user चे ID बदलते. त्यामुळे application ने लिहिलेली प्रत्येक file तुमच्या disk वर 1000 च्या मालकीची म्हणून तयार होते. PUID unset ठेवल्यास abc 911 ठेवतो. म्हणून configuration न केलेला bind mount 911:911 च्या मालकीच्या files ने भरतो.
id वापरून तुमचे दोन क्रमांक मिळवा
डेटा डिरेक्टरींच्या मालकीच्या user म्हणून host वर ही command चालवा:
iduid=1000(deploy) gid=1000(deploy) groups=1000(deploy),27(sudo),988(docker)uid हा तुमचा PUID आहे आणि gid हा तुमचा PGID आहे. Script साठी id -u आणि id -g फक्त क्रमांक दाखवतात. बहुतेक नवीन VPS images मध्ये पहिल्या मानवी user साठी 1000:1000 असते; परंतु ते गृहीत धरू नका. Server पुन्हा तयार केल्यास किंवा नंतर दुसरे account जोडल्यास क्रमांक 1001 किंवा त्याहून अधिक असू शकतो. येथे चुकीचा क्रमांक असल्यास संपूर्ण समस्या त्याचमुळे निर्माण होते. तुमच्या services तुमच्या login user ऐवजी dedicated service account अंतर्गत चालत असल्यास, id thatuser चालवा आणि तेथून क्रमांक घ्या.
तुमच्या फाइल्स 911:911 म्हणून का दिसतात
ls -l त्या ID शी जुळणारे host account नसल्यास नावाऐवजी संख्यात्मक ID दाखवते. तुमच्या सर्व्हरवर UID 911 असलेले कोणतेही 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या output वरून container built-in defaults सह चालला हे स्पष्ट होते. अंदाज न लावता container च्या आतून याची खात्री करा:
docker exec sonarr id abc
docker compose logs sonarr | head -n 25linuxserver init startup log मध्ये त्याचा परिणाम दोन ओळींमध्ये दाखवते:
User UID: 911
User GID: 911तुमच्या Compose file मध्ये PUID=1000 सेट केल्यानंतरही त्या ओळींमध्ये 911 दिसत असल्यास, variable container पर्यंत पोहोचलेला नाही. सामान्य कारण असे असते की तुम्ही docker-compose.yml संपादित करून नंतर docker compose restart चालवले. त्यामुळे विद्यमान container त्याच्या मूळ environment सह पुन्हा वापरला जातो. Environment मधील बदलांसाठी docker compose up -d आवश्यक आहे. यामुळे container पुन्हा तयार केला जातो.
कंटेनरने लिहिलेली फाइल तुम्ही का हटवू शकत नाही
Kernel नावांची नाही, तर क्रमांकांची तुलना करतो. तुमचा shell UID 1000 म्हणून चालतो. ही फाइल UID 911 च्या मालकीची आहे. ती असलेली directory drwxr-xr-x आहे आणि तीदेखील 911 च्या मालकीची आहे. त्यामुळे group आणि other कडे read आणि execute permission आहेत, पण write permission नाही. फाइल हटवण्यासाठी फाइलवर नव्हे, तर तिच्या directory वर write permission आवश्यक असते. म्हणून फाइल स्वतः निरुपद्रवी दिसत असली तरी तुम्हाला हे दिसते:
rm: cannot remove '/srv/appdata/sonarr/config.xml': Permission deniedलिहिणाऱ्या कंटेनरलाही उलट बाजूने हीच अडचण येते. Host directory तुमच्या user च्या मालकीची आणि mode 755 वर असल्यास, application 911 म्हणून चालत असेल तर तिचे पहिले write operation Permission denied मुळे अयशस्वी होते. Application हे कारण स्वतःच्या संदेशात दाखवते. Sonarr किंवा Radarr सारख्या .NET application मध्ये ते UnauthorizedAccessException: Access to the path '/data/downloads' is denied म्हणून दिसते. फाइलच्या सुरुवातीला असलेली permission string तुम्हाला तीन permission sets पैकी कोणत्या संचाच्या आधारे तपासले जात आहे ते सांगते. drwxr-xr-x योग्य प्रकारे वाचणे या error चे कारण गूढ न ठेवता स्पष्ट करते.
ही विशेषतः bind mount ची समस्या आहे. Docker एखादे empty named volume तयार करून ते image मधील आधीपासून अस्तित्वात असलेल्या path वर mount करते, तेव्हा त्या path मधील contents volume मध्ये copy केले जातात. त्यात ownership आणि permission bits देखील समाविष्ट असतात. त्यामुळे application ला आधीपासून आपल्या मालकीची directory मिळते. Bind mount ला अशी कोणतीही प्रक्रिया लागू होत नाही. Docker तुमची host directory जशी आहे तशीच mount करतो. bind mount named volume पेक्षा कधी चांगला ठरतो आणि कधी नाही हे समजून घेण्याचे हे एक व्यावहारिक कारण आहे.
आधीच चुकीच्या असलेल्या directory ची दुरुस्ती
PUID आणि PGID सेट केल्याने application पुढे कसे काम करेल ते बदलते. डिस्कवर आधीपासून असलेल्या files ची पूर्वलक्षी दुरुस्ती यामुळे होत नाही. stack थांबवा, ownership स्वतः दुरुस्त करा आणि त्यानंतर stack पुन्हा सुरू करा:
docker compose down
sudo chown -R 1000:1000 /srv/appdata/sonarr
docker compose up -dतुम्हाला numbers टाइप करायचे नसतील, तर sudo chown -R "$(id -u):$(id -g)" /srv/appdata/sonarr वापरा. हे container थांबवून करा. कारण recursive chown सुरू असताना write करणाऱ्या application मुळे directory tree अंशतः दुरुस्त होऊ शकते आणि errors ची दुसरी, गोंधळात टाकणारी फेरी निर्माण होऊ शकते.
PUID आणि PGID काय दुरुस्त करत नाहीत
सर्वकाही योग्यरीत्या केल्यानंतरही अडचण निर्माण होऊ शकते. linuxserver init startup वेळी नेमके तीन paths वर chown करते: /app, /config आणि /defaults. तुमचे media mounts या यादीत नाहीत. /data, /downloads आणि /tv हे application कडे कोणताही बदल न करता दिले जातात. त्यामुळे या mounts च्या host बाजूवरील ownership मुळे container user ला write करता येत नसेल, तर container व्यवस्थित सुरू होतो, banner मध्ये योग्य UID दाखवतो आणि त्यानंतर पहिल्याच import वेळी अपयशी ठरतो.
हेच योग्य वर्तन आहे. प्रत्येक container start वेळी बारा terabyte media library वर recursive chown चालवणे विनाशकारी ठरेल. त्यामुळे media directories ची जबाबदारी तुमची आहे. Permissions प्रत्यक्षात चुकीच्या ठरणारे mounts हेच आहेत.
वापरकर्त्याचे नियंत्रण करण्याचे तीन मार्ग आणि प्रत्येक कधी वापरावा
PUID आणि PGID environment variables
हे फक्त अशा images वर कार्य करते ज्यांच्या entrypoint मध्ये ही मूल्ये वाचली जातात. ही पद्धत लोकप्रिय आहे, कारण container सुरुवातीला root म्हणून सुरू होतो, स्वतःची setup प्रक्रिया पूर्ण करतो, /config दुरुस्त करतो आणि त्यानंतरच privileges कमी करतो. Docker Mods आणि custom init scripts कार्यरत राहतात. मात्र, यासाठी platform feature ऐवजी एका प्रचलित पद्धतीवर विश्वास ठेवावा लागतो. तसेच variable names सर्व projects मध्ये समान standard चे नाहीत.
Compose मधील user: key
हे Docker चे प्रत्यक्ष feature आहे आणि प्रत्येक image वर कार्य करते, कारण image चा स्वतःचा code चालण्यापूर्वी container runtime हे लागू करते:
services:
sonarr:
image: lscr.io/linuxserver/sonarr:latest
user: "1000:1000"Process root म्हणून कधीही चालत नाही, अगदी क्षणभरही नाही. त्यामुळे प्रत्यक्ष security gain मिळतो. मात्र, entrypoint मध्ये root privileges आवश्यक असलेली कोणतीही गोष्ट यामुळे खंडित होते. linuxserver images मध्ये project हे reasonable endeavours basis वर आणि ज्यांची त्याने चाचणी केली आहे अशाच images साठी याला support देते. यातील मर्यादा स्पष्ट आहेत: PUID आणि PGID चा कोणताही परिणाम होत नाही, Docker Mods चालत नाहीत, custom services चालत नाहीत आणि प्रत्येक mounted volume वरील permissions ची जबाबदारी तुमची राहते. त्यांच्या documented 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 मध्ये matching entry नसते. त्यामुळे आतली tools whoami: cannot find name for user ID 1000 दाखवतात. ID वैध असतो आणि file access नेहमीप्रमाणे कार्य करते. फक्त name lookup अयशस्वी होते.
Rootless Docker
Rootless Docker daemon स्वतः तुमच्या unprivileged user म्हणून चालवतो. त्यामुळे host वरील कोणतीही गोष्ट खऱ्या root म्हणून चालत नाही. यामुळे ownership arithmetic पूर्णपणे बदलते. Container UID 0 हा rootless Docker चालवणाऱ्या user च्या host UID शी map होतो. तसेच n चे मूल्य 1 किंवा त्याहून अधिक असताना container UID n हा subuid + (n - 1) शी map होतो. येथे subuid हा /etc/subuid आणि /etc/subgid मध्ये तुमच्यासाठी allocated range चा base असतो. Docker ला तेथे किमान 65,536 subordinate IDs अपेक्षित असतात.
हे mapping पुन्हा वाचा, कारण यामुळे नेहमीचा सल्ला उलटा लागू होतो. Rootless Docker अंतर्गत root म्हणून लिहिणारा container तुमच्या मालकीच्या files तयार करतो. UID 1000 म्हणून लिहिणारा container सुमारे 100999 सारख्या subordinate ID च्या मालकीच्या files तयार करतो. तुमच्या shell ला त्या files मध्ये प्रवेश करता येत नाही. त्यामुळे rootful daemon वर योग्य असलेले PUID value येथे चुकीचे ठरते. हे दोन्ही mechanisms वेगवेगळ्या layers मध्ये समान समस्या सोडवतात. तपासणी न करता दोन्ही एकत्र वापरल्यास अशी directory तयार होऊ शकते जी काढण्यासाठी तुम्हाला sudo आवश्यक असेल. Rootless वापरणार असल्यास library migrate करण्यापूर्वी तुमच्या server वर लिहिलेल्या एका file ची ownership तपासा.
Single VPS वरील बहुतेक self-hosted stacks साठी rootful daemon वर PUID आणि PGID वापरणे हा व्यावहारिक पर्याय आहे. Images याच पद्धतीसाठी तयार आणि documented केलेल्या असतात. Image README मध्ये त्या image साठी याची चाचणी केल्याचे नमूद असल्यास, किंवा PUID support नसलेली official upstream image वापरत असल्यास user: वापरा. एका VPS वरील self-hosted AFFiNE instance याच शेवटच्या प्रकारात येते. त्याच्या कोणत्याही containers मध्ये PUID वाचला जात नाही. त्यामुळे database directory आणि uploaded files ची ownership environment block मधील कोणत्याही setting ऐवजी runtime ठरवतो.
कंटेनरमध्ये सामायिक केलेल्या एका group चे media stack उदाहरण
Sonarr, Radarr आणि download client असलेला arr media stack हे प्रत्यक्ष उदाहरण आहे. download client पूर्ण झालेली file /data/downloads मध्ये लिहितो. त्यानंतर Sonarr ती file hardlink करतो किंवा /data/media मध्ये हलवतो. hardlink कार्य करण्यासाठी दोन्ही containers ना त्याच tree वर write access आवश्यक असतो. download client 1000 म्हणून चालत असेल आणि Sonarr 1001 म्हणून चालत असेल, तर त्यांपैकी एकाने तयार केलेल्या files दुसरा container फक्त read करू शकतो.
यासाठी stack मधील प्रत्येक container ने PGID म्हणून वापरणारा shared group तयार करा:
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 bit आहे. Directory वर याचा अर्थ असा होतो की त्यामध्ये तयार होणाऱ्या प्रत्येक नवीन file आणि subdirectory ला creator च्या स्वतःच्या primary group ऐवजी media हा group वारशाने मिळतो. त्यामुळे प्रत्येक नवीन download नंतर chown पुन्हा चालवण्याची गरज राहत नाही. स्वतःचा access तपासण्यापूर्वी log out करून पुन्हा log in करा किंवा newgrp media चालवा. usermod -aG ने जोडलेला group आधीच उघडलेल्या shell session मध्ये दिसत नाही.
Container मध्ये groupmod -o -g 13000 abc हे abc group ला 13000 वर renumber करते. त्यामुळे abc तुमच्या host वरील media group सारख्या GID ने files लिहिते. Stack मधील प्रत्येक container स्वतःचा PUID ठेवतो आणि तोच एक PGID सामायिक करतो.
यानंतर stack मधील प्रत्येक linuxserver container वर UMASK=002 सेट करा. बहुतेक वेळा हा टप्पा वगळला जातो. या images मधील default UMASK=022 आहे. त्यामुळे प्रत्येक नवीन file मधील group write bit काढला जातो. परिणामी files 0644 म्हणून तयार होतात आणि तुम्ही केलेली sharing configuration कार्य करत नाही. 002 मुळे 0664 files आणि 0775 directories तयार होतात आणि group ला write करता येते:
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ही दोन्ही values Compose file च्या शेजारील .env file मध्ये ठेवा. त्यामुळे संपूर्ण stack एकाच definition मधून values वाचतो:
PUID=1000
PGID=13000Compose ही file ${PUID} प्रकारच्या substitution साठी आपोआप वाचते. Credentials साठीही हीच पद्धत वापरली जाते. values docker-compose.yml मध्ये न ठेवता .env file मध्ये ठेवण्याची पद्धत येथेही लागू होते. मात्र या दोन numbers गुप्त नाहीत.
Configuration वर अवलंबून न राहता end to end पडताळणी करा. एका container मधून file लिहा आणि host वरून ती read करा:
docker exec sonarr touch /data/downloads/permtest
ls -ln /srv/media/downloads/permtestयशस्वी परिणामात तुमचा PUID owner म्हणून, 13000 group म्हणून आणि -rw-rw-r-- mode म्हणून दिसतो. Group म्हणून 1000 दिसत असेल, तर त्या directory मधून setgid bit गहाळ आहे. Mode म्हणून -rw-r--r-- दिसत असेल, तर UMASK variable लागू झालेला नाही. त्यामुळे तुम्ही container restart करण्याऐवजी तो recreate केला आहे का ते तपासा. काम पूर्ण झाल्यावर rm /srv/media/downloads/permtest ने test file काढून टाका.
कोणती image कोणते variable वापरते
linuxserver.io images PUID, PGID आणि UMASK वापरतात. Paperless-ngx मध्ये याच संकल्पनेसाठी वेगळी नावे आहेत: USERMAP_UID आणि USERMAP_GID. दोन्हींचे default मूल्य 1000 आहे. त्यांची कागदपत्रे ही मूल्ये id -u आणि id -g मधून वाचण्यास सांगतात. Photo server मध्येही अशीच विविधता दिसते. PhotoPrism स्वतःची PHOTOPRISM_UID आणि PHOTOPRISM_GID ही जोडी वापरते. Immich मध्ये यासाठी समतुल्य variable नाही. त्याऐवजी container user Docker च्या user: key वर अवलंबून असतो. त्यामुळे PhotoPrism आणि Immich यांपैकी निवडणे म्हणजे या server वरील सर्वात मोठ्या library साठी तुम्ही यापैकी कोणती यंत्रणा व्यवस्थापित करणार हे ठरवणे होय. अनेक अधिकृत upstream images, ज्यात सामान्य database आणि web server images समाविष्ट आहेत, fixed built-in user वापरतात आणि तुम्ही user: वापरावे किंवा ते तसेच ठेवावे अशी अपेक्षा करतात. नंतर जोडलेल्या infrastructure बाबतीतही हेच लागू होते. त्यामुळे एकाच login साठी तुमच्या apps समोर Authentik ठेवणे म्हणजे official server, Postgres आणि Redis images चालवणे होय. ही images PUID अजिबात वाचत नाहीत. त्यांच्या volume ची ownership runtime कडून ठरते; तुम्ही configure करू शकणाऱ्या entrypoint कडून नाही.
म्हणून projects मध्ये environment block copy करण्यापूर्वी प्रत्येक image चे README तपासा. तुम्ही set केलेले कोणतेही environment variable Docker कोणत्याही container मध्ये पाठवतो, त्याच्या आतले काही ते वाचते किंवा नाही याची पर्वा न करता. काहीही वापरत नसलेले PUID set केल्यास कोणतीही error, warning किंवा परिणाम निर्माण होत नाही. Container स्वतःच्या Dockerfile मध्ये शेवटी निश्चित केलेल्या user म्हणून चालतो. तो कोणता user आहे हे त्याने लिहिलेल्या files च्या ownership वरून समजते.
FAQ
माझ्या Docker files चे मालक 911:911 का आहेत?
911 हा linuxserver.io images मध्ये अंगभूत असलेल्या abc user चा UID आणि GID आहे. याचा अर्थ container PUID आणि PGID सेट न करता सुरू झाला आणि त्यामुळे त्याच्या init script ने अंगभूत default values तशाच ठेवल्या. तुमच्या host वर ID 911 असलेले कोणतेही account नसल्यामुळे ls -l कच्चे numbers दाखवते; दाखवण्यासाठी कोणतेही नाव उपलब्ध नसते. PUID आणि PGID मध्ये id चा output सेट करा, docker compose up -d वापरून container पुन्हा तयार करा, आणि प्रभावित directory मधील विद्यमान files sudo chown -R 1000:1000 वापरून दुरुस्त करा.
प्रत्येक Docker image वर PUID आणि PGID कार्य करतात का?
नाही. ते Docker चे feature नाहीत आणि Docker ते कधीही वाचत नाही. ज्या images चा स्वतःचा entrypoint त्यांना वाचतो आणि application सुरू करण्यापूर्वी usermod आणि groupmod चालवतो, त्यांच्यावरच ते कार्य करतात. यामध्ये linuxserver.io family आणि ही पद्धत स्वीकारलेले काही projects येतात. इतर projects इतर names वापरतात; उदाहरणार्थ, paperless-ngx मध्ये USERMAP_UID आणि USERMAP_GID वापरले जातात. ज्या image ला यापैकी कोणतेही variables वाचता येत नाहीत, त्या image मध्ये variables स्वीकारले जातात आणि कोणतीही warning न देता दुर्लक्षित केले जातात.
Docker Compose मध्ये PUID आणि PGID वापरावे की user: key?
Image त्यांना support करत असल्यास PUID आणि PGID वापरा. कारण entrypoint root म्हणून पुरेसा वेळ चालतो, त्यामुळे /config दुरुस्त करून स्वतःच्या services योग्यरीत्या सुरू करू शकतो. Image ला PUID support नसल्यास, किंवा non-root operation साठी ते tested असल्याचे image README मध्ये नमूद असल्यास user: वापरा. linuxserver image वर user: सेट केल्यास PUID आणि PGID निष्क्रिय होतात, Docker Mods आणि custom services चालणे थांबते आणि प्रत्येक mounted volume च्या permissions ची जबाबदारी तुमच्यावर येते.
Sonarr कडे योग्य PUID असूनही files हलवता येत नाहीत. समस्या काय आहे?
खालील तीन गोष्टी क्रमाने तपासा. प्रथम, media mount स्वतः तपासा: init फक्त /app, /config आणि /defaults वर chown चालवते. त्यामुळे /data किंवा /downloads ची host वरील ownership जशी आहे तशीच राहते. दुसरे, shared group तपासा: download client आणि Sonarr वेगवेगळ्या GIDs अंतर्गत चालत असल्यास एकमेकांच्या files मध्ये बदल करता येत नाही. त्यामुळे stack मधील प्रत्येक container साठी समान PGID द्या. तिसरे, umask तपासा: image मधील default UMASK=022 files 0644 म्हणून लिहिते आणि group write bit ठेवत नाही. त्यामुळे shared group पूर्णपणे निष्प्रभ होते. UMASK=002 सेट करा आणि chmod 2775 वापरून directories वर setgid bit सेट करा, जेणेकरून नवीन files ना group वारशाने मिळेल.