SSD Nodes Learn Hosting plans →
নির্দেশিকা Matt Connorদ্বারা Matt Connor · আপডেট করা হয়েছে 2026-09-23

Docker Compose-এ PUID এবং PGID কেন ব্যবহার করবেন?

PUID এবং PGID আসলে Docker সেটিংস নয় বরং linuxserver.io ইমেজের একটি কনভেনশন। কেন আপনার ফাইলগুলো 911:911 মালিকানায় তৈরি হয় এবং কীভাবে সঠিক UID ও GID সেট করবেন তা জানুন।

PUID এবং PGID আসলে কী

PUID এবং PGID হলো দুটি environment variable যা নির্দিষ্ট কিছু container image স্টার্টআপের সময় পড়ে নেয়। Docker নিজে কখনো এগুলো পরীক্ষা করে না। এটি একটি প্রচলিত নিয়ম, যা linuxserver.io-এর image এবং আরও কিছু ক্ষেত্রে ব্যবহৃত হয়। তাই যে image-গুলো এই variable পড়ার জন্য তৈরি করা হয়নি, সেগুলো এগুলোকে উপেক্ষা করে।

একটি linuxserver.io image-এর ভেতরে abc নামে একজন ব্যবহারকারী থাকে, যাকে build করার সময় UID (user ID) 911 এবং GID (group ID) 911 দিয়ে তৈরি করা হয়। container-টি root হিসেবে চালু হয় এবং এর init scriptগুলো চালায়। অ্যাপ্লিকেশন শুরু হওয়ার আগেই একটি script সেই ব্যবহারকারীর ID পরিবর্তন করে ফেলে:

groupmod -o -g "${PGID}" abc
usermod -o -u "${PUID}" abc

-o flag-টি এমন একটি ID ব্যবহারের অনুমতি দেয় যা অন্য কোথাও ব্যবহৃত হচ্ছে। এরপর init প্রক্রিয়াটি privileges কমিয়ে অ্যাপ্লিকেশনটিকে abc হিসেবে চালায়। তাই PUID=1000 কখনোই Docker-এর কাছে পৌঁছায় না। এই variable-টি অ্যাপ্লিকেশন শুরু হওয়ার আগেই container-এর ভেতরের ব্যবহারকারীর ID পরিবর্তন করে দেয়। এর মানে হলো, অ্যাপ্লিকেশনটি যে ফাইলগুলো লেখে, সেগুলো আপনার ডিস্কে 1000 মালিকানাধীন হিসেবে জমা হয়। PUID সেট না করলে abc এর মান 911-ই থেকে যায়। এই কারণেই কনফিগার না করা bind mount-এ তৈরি হওয়া ফাইলগুলোর মালিক 911:911 হয়ে থাকে।

id ব্যবহার করে আপনার দুটি নম্বর সংগ্রহ করুন

ডেটা ডিরেক্টরির মালিক এমন ব্যবহারকারী হিসেবে হোস্ট মেশিনে নিচের কমান্ডটি চালান:

id
uid=1000(deploy) gid=1000(deploy) groups=1000(deploy),27(sudo),988(docker)

uid হলো আপনার PUID এবং gid হলো আপনার PGID। কোনো স্ক্রিপ্টের জন্য, id -u এবং id -g সরাসরি কেবল নম্বরগুলো প্রদর্শন করবে। বেশিরভাগ নতুন VPS ইমেজে প্রথম হিউম্যান অ্যাকাউন্টের আইডি সাধারণত 1000:1000 হয়, তবে এটি ধরে নেওয়া ঠিক হবে না। সার্ভার রিবিল্ড করলে বা পরে নতুন কোনো অ্যাকাউন্ট যোগ করলে আইডি 1001 বা তার বেশি হতে পারে, আর এখানে ভুল নম্বর দেওয়া মানেই পুরো কনফিগারেশনে ত্রুটি থাকা। যদি আপনার সার্ভিসগুলো আপনার নিজস্ব লগইন ব্যবহারকারীর পরিবর্তে একটি ডেডিকেটেড সার্ভিস অ্যাকাউন্টের অধীনে চলে, তবে id thatuser চালান এবং সেখান থেকে নম্বরগুলো সংগ্রহ করুন।

কেন আপনার ফাইলগুলো 911:911 হিসেবে দেখাচ্ছে

যখন কোনো হোস্ট অ্যাকাউন্টের সাথে ওই ID-এর মিল পাওয়া যায় না, তখন ls -l নামের পরিবর্তে একটি সংখ্যাসূচক ID প্রদর্শন করে। আপনার সার্ভারে কোনো কিছুর UID 911 নয়, তাই প্রদর্শন করার মতো কোনো নাম নেই। প্রতিবার সংখ্যা দেখার জন্য এবং অস্পষ্টতা দূর করতে ls -ln ব্যবহার করুন:

ls -ln /srv/appdata/sonarr
drwxr-xr-x 2 911 911 4096 Aug  7 09:12 Backups
-rw-r--r-- 1 911 911  512 Aug  7 09:12 config.xml

এই আউটপুটটি নির্দেশ করে যে কন্টেইনারটি বিল্ট-ইন ডিফল্ট সেটিংস নিয়ে চলেছে। এই তালিকার config.xml ফাইলটি সেই ফাইল যা অথেন্টিকেশন সেটিংস ধারণ করে, যা প্রথমবার ওয়েব UI খোলার সময় গুরুত্বপূর্ণ হয়ে ওঠে যখন আপনি দেখেন যে Sonarr এবং Radarr কোনো ডিফল্ট ইউজারনেম বা পাসওয়ার্ড ছাড়াই আসে। অনুমান না করে কন্টেইনারের ভেতর থেকে এটি নিশ্চিত করুন:

docker exec sonarr id abc
docker compose logs sonarr | head -n 25

linuxserver ইনিট তার ফলাফল স্টার্টআপ লগে দুটি লাইনে প্রিন্ট করে:

User UID:    911
User GID:    911

যদি আপনার Compose ফাইলে PUID=1000 সেট করার পরেও সেই লাইনগুলোতে 911 দেখায়, তবে ভেরিয়েবলটি কন্টেইনারে পৌঁছায়নি। এর সাধারণ কারণ হলো আপনি docker-compose.yml এডিট করেছেন এবং তারপর docker compose restart চালিয়েছেন, যা কন্টেইনারের মূল এনভায়রনমেন্টসহ সেটিকে পুনরায় ব্যবহার করে। এনভায়রনমেন্ট পরিবর্তনের জন্য docker compose up -d প্রয়োজন, যা কন্টেইনারটিকে নতুন করে তৈরি করে।

কেন আপনি কন্টেইনারের তৈরি করা কোনো ফাইল ডিলিট করতে পারেন না

কার্নেল ফাইলের নামের পরিবর্তে সংখ্যা (UID/GID) তুলনা করে। আপনার শেল UID 1000 হিসেবে চলে, কিন্তু ফাইলটির মালিকানা UID 911-এর। ফাইলটি যে ডিরেক্টরিতে আছে সেটিও drwxr-xr-x এবং সেটির মালিকানাও 911-এর, তাই group এবং other-এর জন্য শুধু read এবং execute অনুমতি আছে, কিন্তু write অনুমতি নেই। কোনো ফাইল ডিলিট করার জন্য ফাইলটিতে নয়, বরং ফাইলটি যে ডিরেক্টরিতে আছে সেখানে write অনুমতি থাকা প্রয়োজন। তাই ফাইলটি দেখতে সাধারণ মনে হলেও আপনি এই সমস্যার সম্মুখীন হন:

rm: cannot remove '/srv/appdata/sonarr/config.xml': Permission denied

একটি write-এর কাজ করা কন্টেইনার উল্টো দিক থেকে একই বাধার সম্মুখীন হয়। যদি হোস্ট ডিরেক্টরিটি আপনার ব্যবহারকারীর মালিকানাধীন হয় এবং mode 755-এ থাকে, আর অ্যাপ্লিকেশনটি 911 হিসেবে চলে, তবে প্রথমবার write করার সময় সেটি Permission denied ত্রুটির কারণে ব্যর্থ হবে এবং অ্যাপ্লিকেশনটি তার নিজস্ব ভাষায় এটি রিপোর্ট করবে। Sonarr বা Radarr-এর মতো .NET অ্যাপ্লিকেশনের ক্ষেত্রে এটি UnauthorizedAccessException: Access to the path '/data/downloads' is denied হিসেবে দেখা দেয়। ফাইলের নামের আগে থাকা permission string আপনাকে বলে দেয় যে তিনটি permission set-এর মধ্যে কোনটি দিয়ে আপনাকে যাচাই করা হচ্ছে, এবং drwxr-xr-x সঠিকভাবে পড়া শিখলে এই রহস্যময় ত্রুটিগুলো সহজেই বোঝা যায়।

এটি মূলত একটি bind mount সংক্রান্ত সমস্যা। যখন Docker একটি empty named volume তৈরি করে এবং সেটিকে ইমেজে থাকা কোনো পাথ-এর ওপর mount করে, তখন এটি সেই পাথ-এর বিষয়বস্তু ভলিউমে কপি করে নেয় (মালিকানা এবং permission bit সহ), ফলে অ্যাপ্লিকেশনটি এমন একটি ডিরেক্টরি পায় যার মালিকানা তার নিজেরই। bind mount-এর ক্ষেত্রে এমনটি ঘটে না: Docker আপনার হোস্ট ডিরেক্টরিটিকে ঠিক যেভাবে আছে সেভাবেই mount করে। এই পার্থক্যটিই হলো কখন bind mount ব্যবহার করবেন আর কখন named volume ব্যবহার করবেন তা জানার অন্যতম ব্যবহারিক কারণ।

ইতিমধ্যে ভুল হয়ে থাকা ডিরেক্টরি ঠিক করা

PUID এবং PGID সেট করলে অ্যাপ্লিকেশনটি এখন থেকে যেভাবে কাজ করবে তা পরিবর্তিত হয়। এটি ডিস্কে থাকা বিদ্যমান ফাইলগুলোকে স্বয়ংক্রিয়ভাবে ঠিক করে না। স্ট্যাকটি বন্ধ করুন, নিজেই মালিকানা (ownership) সংশোধন করুন, তারপর এটি পুনরায় চালু করুন:

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 init স্টার্টআপের সময় ঠিক তিনটি পাথ chown করে: /app, /config এবং /defaults। আপনার মিডিয়া মাউন্টগুলো এই তালিকার অন্তর্ভুক্ত নয়। /data, /downloads এবং /tv অ্যাপ্লিকেশনকে অপরিবর্তিত অবস্থায় দেওয়া হয়। তাই যদি এই মাউন্টগুলোর হোস্ট সাইডে এমন মালিকানা থাকে যেখানে কন্টেইনার ব্যবহারকারীর লেখার অনুমতি নেই, তবে কন্টেইনারটি সঠিকভাবে চালু হবে, ব্যানারে সঠিক UID দেখাবে, কিন্তু প্রথম ইমপোর্ট করার সময় ব্যর্থ হবে।

এটিই সঠিক আচরণ। প্রতিবার কন্টেইনার চালু হওয়ার সময় বারো টেরাবাইট মিডিয়া লাইব্রেরিতে রিকার্সিভ chown চালানো একটি বিপর্যয় ডেকে আনবে। এর মানে হলো মিডিয়া ডিরেক্টরিগুলোর দায়িত্ব আপনার, এবং এগুলোতে অনুমতি সংক্রান্ত সমস্যা হওয়ার সম্ভাবনা বেশি থাকে। যেহেতু এই ধরনের ব্যর্থতা কন্টেইনার চালু হওয়ার কয়েক ঘণ্টা পর অ্যাপ্লিকেশন লগে নীরবে ধরা পড়ে, তাই আপনার নিজস্ব VPS-এ ntfy সেটআপ করে ফোনে সতর্কতা পাঠানো একটি সাশ্রয়ী উপায়, যার মাধ্যমে এক সপ্তাহ ধরে এপিসোড মিস হওয়ার আগেই আপনি সমস্যাটি সম্পর্কে জানতে পারবেন।

ব্যবহারকারী নিয়ন্ত্রণ করার তিনটি উপায় এবং প্রতিটি কখন প্রযোজ্য

PUID এবং PGID এনভায়রনমেন্ট ভেরিয়েবল

এটি শুধুমাত্র সেইসব ইমেজে কাজ করে যেগুলোর এন্ট্রি পয়েন্ট এগুলো রিড করতে পারে। এটি জনপ্রিয় কারণ কন্টেইনারটি শুরুতেই root হিসেবে চালু হয়, নিজস্ব সেটআপ সম্পন্ন করে, /config ঠিক করে এবং তারপর প্রিভিলেজ বা বিশেষ সুবিধা ত্যাগ করে। Docker Mods এবং কাস্টম ইনিট স্ক্রিপ্টগুলো এতে কাজ করতে থাকে। এর অসুবিধা হলো, আপনি প্ল্যাটফর্ম ফিচারের পরিবর্তে একটি কনভেনশনের ওপর নির্ভর করছেন এবং ভেরিয়েবলের নামগুলো সব প্রজেক্টে একরকম নয়।

Compose-এ user: কি (key)

এটি একটি প্রকৃত Docker ফিচার এবং এটি প্রতিটি ইমেজে কাজ করে, কারণ কন্টেইনার রানটাইম ইমেজের নিজস্ব কোড চলার আগেই এটি প্রয়োগ করে:

services:
  sonarr:
    image: lscr.io/linuxserver/sonarr:latest
    user: "1000:1000"

প্রসেসটি কখনোই root হিসেবে চলে না, এমনকি এক মুহূর্তের জন্যও নয়, যা নিরাপত্তার দিক থেকে একটি বড় অর্জন। এটি এন্ট্রি পয়েন্টের এমন যেকোনো কিছুকে অকেজো করে দেয় যার জন্য root প্রয়োজন ছিল। linuxserver ইমেজগুলোতে প্রজেক্টটি শুধুমাত্র পরীক্ষিত ইমেজগুলোর জন্য এটি সমর্থন করে এবং এর কিছু সীমাবদ্ধতা রয়েছে: PUID এবং PGID আর কোনো কাজ করে না, Docker Mods চলবে না, কাস্টম সার্ভিস চলবে না এবং মাউন্ট করা প্রতিটি ভলিউমের পারমিশনের দায়িত্ব আপনার ওপর বর্তাবে। তাদের নথিপত্র অনুযায়ী এই ফ্ল্যাগটির সাথে একটি রাইটেবল /run ব্যবহার করা হয়:

user: 1000:1000
tmpfs:
  - /run:uid=1000,gid=1000,exec
security_opt:
  - no-new-privileges=true

একটি ছোট কসমেটিক পার্শ্বপ্রতিক্রিয়া ব্যবহারকারীদের অবাক করে। একটি সংখ্যাসূচক user:-এর জন্য কন্টেইনারের /etc/passwd-এ কোনো এন্ট্রি থাকে না, তাই ভেতরের টুলগুলো whoami: cannot find name for user ID 1000 রিপোর্ট করে। আইডিটি বৈধ এবং ফাইল অ্যাক্সেস স্বাভাবিকভাবেই কাজ করে। শুধুমাত্র নাম খোঁজার প্রক্রিয়াটি ব্যর্থ হয়।

Rootless Docker

Rootless Docker ডেমোনটিকে আপনার আনপ্রিভিলেজড ব্যবহারকারী হিসেবে চালায়, তাই সার্ভারে কোনো কিছুই প্রকৃত root হিসেবে চলে না। এটি মালিকানার হিসাব সম্পূর্ণ বদলে দেয়। কন্টেইনার UID 0 ম্যাপ হয় rootless Docker চালানো হোস্ট ব্যবহারকারীর UID-তে, এবং 1 বা তার বেশি যেকোনো n-এর জন্য কন্টেইনার UID n ম্যাপ হয় subuid + (n - 1)-তে, যেখানে subuid হলো /etc/subuid এবং /etc/subgid-এ আপনার জন্য বরাদ্দকৃত রেঞ্জের ভিত্তি। Docker সেখানে অন্তত 65,536টি সাবঅর্ডিনেট আইডি আশা করে।

এই ম্যাপিংটি আবার পড়ুন, কারণ এটি প্রচলিত ধারণার বিপরীত। Rootless Docker-এ root হিসেবে লেখা কোনো কন্টেইনার আপনার মালিকানাধীন ফাইল তৈরি করে। UID 1000 হিসেবে লেখা কোনো কন্টেইনার এমন কোনো সাবঅর্ডিনেট আইডিতে ফাইল তৈরি করে যা প্রায় 100999-এর কাছাকাছি, যা আপনার শেল অ্যাক্সেস করতে পারে না। তাই rootful ডেমোনে যে PUID সঠিক ছিল, এখানে তা ভুল। এই দুটি মেকানিজম ভিন্ন ভিন্ন স্তরে একই সমস্যার সমাধান করে, এবং যাচাই না করে এগুলো একসাথে ব্যবহার করলে এমন ডিরেক্টরি তৈরি হতে পারে যা রিমুভ করতে আপনার sudo প্রয়োজন হবে। আপনি যদি rootless ব্যবহার করেন, তবে কোনো লাইব্রেরি মাইগ্রেট করার আগে আপনার সার্ভারে একটি ফাইল লিখে তার মালিকানা পরীক্ষা করে নিন।

একটি সিঙ্গেল VPS-এ বেশিরভাগ self-hosted স্ট্যাকের জন্য rootful ডেমোনে PUID এবং PGID ব্যবহার করাই বাস্তবসম্মত, কারণ ইমেজগুলো এভাবেই তৈরি এবং ডকুমেন্ট করা হয়েছে। user: ব্যবহার করুন যখন ইমেজের README-তে বলা থাকে যে এটি এর জন্য পরীক্ষিত, অথবা যখন আপনি এমন কোনো অফিসিয়াল আপস্ট্রিম ইমেজ চালাচ্ছেন যাতে কোনো PUID সাপোর্ট নেই। একটি সিঙ্গেল VPS-এ self-hosted AFFiNE instance-এর মতো ডকুমেন্ট ওয়ার্কস্পেস এই শেষ ক্যাটাগরিতে পড়ে, কারণ এর কোনো কন্টেইনারই PUID রিড করে না এবং এর ডাটাবেস ডিরেক্টরি ও আপলোড করা ফাইলের মালিকানা এনভায়রনমেন্ট ব্লকের পরিবর্তে রানটাইম দ্বারা নির্ধারিত হয়। একটি self-hosted Chatwoot support desk-এর ক্ষেত্রেও একই কথা প্রযোজ্য, যেখানে Rails কন্টেইনার এবং এর Sidekiq ওয়ার্কার উভয়ই একটি আপলোড ডিরেক্টরিতে লেখে এবং কেউই PUID রিড করে না, তাই সেই ডিরেক্টরিটিকে ইমেজের ডিফল্ট ব্যবহারকারীর সাথে মিল রাখতে হয়। নতুন স্ট্যাকের ক্ষেত্রেও এর কোনো পরিবর্তন নেই, তাই দলের প্রত্যেক সদস্যকে তাদের নিজস্ব স্যান্ডবক্সড OneCLI agent দেওয়া-র ফলে প্রতিটি ব্যক্তির ওয়ার্কস্পেস ডিরেক্টরি এবং Postgres ডাটা ডিরেক্টরির মালিকানা সেই ব্যবহারকারীর কাছেই থাকে যা ইমেজটি ডিফল্টভাবে ব্যবহার করে, যা এটিকে PUID-এর পরিবর্তে একটি user: এবং chown সমস্যায় পরিণত করে। Codex, Claude Code এবং Hermes-এর সামনে একটি সিঙ্গেল self-hosted API বসান এবং আপনি একই ব্যবস্থা পাবেন, কারণ সেই ইমেজটি তার নিজস্ব বিল্ট-ইন ব্যবহারকারী হিসেবে চলে এবং ডাটাবেস ও সংরক্ষিত কি (key) ধারণকারী বাইন্ড মাউন্টটি সেই ব্যবহারকারীর মালিকানাই গ্রহণ করে।

মিডিয়া স্ট্যাকের ক্ষেত্রে: কন্টেইনারগুলোর মধ্যে একটি গ্রুপ শেয়ার করা

একটি Sonarr, Radarr এবং একটি ডাউনলোড ক্লায়েন্ট সম্বলিত arr মিডিয়া স্ট্যাক হলো এমন একটি ক্ষেত্র যেখানে এটি কেবল তত্ত্বে সীমাবদ্ধ থাকে না। ডাউনলোড ক্লায়েন্ট একটি সম্পন্ন ফাইল /data/downloads ডিরেক্টরিতে লেখে। এরপর Sonarr সেই ফাইলটিকে হার্ডলিঙ্ক করে বা সরিয়ে /data/media ডিরেক্টরিতে নিয়ে যায়। হার্ডলিঙ্ক কাজ করার জন্য দুটি কন্টেইনারেরই একই ডিরেক্টরি ট্রিতে রাইট অ্যাক্সেস থাকতে হয়। যদি ডাউনলোড ক্লায়েন্ট 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 গ্রুপটি উত্তরাধিকার সূত্রে পায়। ফলে নতুন ডাউনলোড আসার পরেও এই ব্যবস্থাটি কার্যকর থাকে এবং আপনাকে পুনরায় chown চালাতে হয় না। আপনার নিজের অ্যাক্সেস যাচাই করার আগে লগ আউট করে পুনরায় লগ ইন করুন অথবা newgrp media কমান্ডটি চালান; কারণ usermod -aG দিয়ে যোগ করা কোনো গ্রুপ আগে থেকে খোলা শেল সেশনে দেখা যায় না।

কন্টেইনারের ভেতরে, groupmod -o -g 13000 abc কমান্ডটি abc গ্রুপকে 13000-এ রিনাম্বার করে, যাতে abc আপনার হোস্টের media গ্রুপের সমান GID দিয়ে ফাইল লিখতে পারে। স্ট্যাকের প্রতিটি কন্টেইনার তার নিজস্ব PUID বজায় রাখে কিন্তু একই PGID শেয়ার করে। এর মধ্যে সেই কন্টেইনারগুলোও অন্তর্ভুক্ত, যেগুলো কেবল সম্পন্ন লাইব্রেরিটি পড়ে, যেমন Jellyfin এবং এর সাথে যুক্ত ফ্রন্ট-এন্ডগুলো, যেমন Halcyon, যা সেই লাইব্রেরিটিকে নব্বইয়ের দশকের ভিডিও স্টোরের মতো উপস্থাপন করে।

এরপর স্ট্যাকের প্রতিটি linuxserver কন্টেইনারে UMASK=002 সেট করুন। এটিই সেই ধাপ যা মানুষ প্রায়ই ভুলে যায়। এই ইমেজগুলোতে ডিফল্ট মান থাকে UMASK=022, যা প্রতিটি নতুন ফাইল থেকে গ্রুপের রাইট বিট সরিয়ে দেয়। ফলে ফাইলগুলো 0644 মোডে তৈরি হয় এবং আপনার কনফিগার করা শেয়ারিং কোনো কাজে আসে না। 002 ব্যবহার করলে 0664 ফাইল এবং 0775 ডিরেক্টরি তৈরি হয়, ফলে গ্রুপ ফাইল লিখতে পারে:

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=13000

Compose স্বয়ংক্রিয়ভাবে ${PUID} স্টাইল সাবস্টিটিউশনের জন্য এই ফাইলটি পড়ে, যা আপনি ক্রেডেনশিয়ালের জন্য ব্যবহার করেন। docker-compose.yml ফাইল থেকে মানগুলো সরিয়ে .env ফাইলে রাখার অভ্যাস এখানেও প্রযোজ্য, তবে পার্থক্য হলো এই দুটি সংখ্যা গোপন রাখার প্রয়োজন নেই।

কনফিগারেশনের ওপর ভরসা না করে সরাসরি যাচাই করুন। একটি কন্টেইনারের ভেতর থেকে একটি ফাইল তৈরি করুন এবং হোস্ট থেকে সেটি পড়ুন:

docker exec sonarr touch /data/downloads/permtest
ls -ln /srv/media/downloads/permtest

সঠিক ফলাফলে আপনার PUID মালিক হিসেবে, 13000 গ্রুপ হিসেবে এবং -rw-rw-r-- মোড হিসেবে দেখাবে। যদি গ্রুপে 1000 দেখা যায়, তবে ডিরেক্টরিতে setgid বিট অনুপস্থিত। যদি মোড -rw-r--r-- দেখায়, তবে UMASK ভেরিয়েবলটি কার্যকর হয়নি; সেক্ষেত্রে কন্টেইনারটি রিস্টার্ট না করে পুনরায় তৈরি (recreate) করেছেন কি না তা নিশ্চিত করুন। কাজ শেষ হলে rm /srv/media/downloads/permtest দিয়ে টেস্ট ফাইলটি মুছে ফেলুন।

কোন ইমেজ কোন ভেরিয়েবল ব্যবহার করে

linuxserver.io ইমেজগুলো PUID, PGID এবং UMASK ব্যবহার করে। Paperless-ngx একই ধারণার জন্য ভিন্ন নাম ব্যবহার করে: USERMAP_UID এবং USERMAP_GID, যার উভয়ই ডিফল্ট হিসেবে 1000 থাকে এবং এর ডকুমেন্টেশন আপনাকে id -u ও id -g থেকে সেগুলো পড়ার পরামর্শ দেয়। ফটো সার্ভারগুলোর ক্ষেত্রেও একই বৈচিত্র্য দেখা যায়: PhotoPrism-এর নিজস্ব PHOTOPRISM_UID এবং PHOTOPRISM_GID জোড়া রয়েছে, অন্যদিকে Immich-এর কোনো সমতুল্য ভেরিয়েবল নেই এবং এটি কন্টেইনার ব্যবহারকারীকে Docker-এর user: কী-এর ওপর ছেড়ে দেয়। তাই PhotoPrism এবং Immich-এর মধ্যে নির্বাচন করার মাধ্যমে আপনি সিদ্ধান্ত নিচ্ছেন যে আপনার সার্ভারের সবচেয়ে বড় লাইব্রেরির জন্য এই মেকানিজমগুলোর কোনটি আপনি রক্ষণাবেক্ষণ করবেন। অনেক অফিসিয়াল আপস্ট্রিম ইমেজ, যার মধ্যে সাধারণ ডাটাবেস এবং ওয়েব সার্ভার ইমেজ অন্তর্ভুক্ত, একটি নির্দিষ্ট বিল্ট-ইন ব্যবহারকারী নিয়ে আসে এবং আশা করে যে আপনি user: ব্যবহার করবেন অথবা সেটি পরিবর্তন করবেন না। ছোট একক অ্যাপ ডেপ্লয়মেন্টের ক্ষেত্রেও একই প্রশ্ন ওঠে, তাই যখন আপনি একটি self-hosted openGym workout tracker সেটআপ করেন, তখন সেটিতে bind mount পয়েন্ট করার আগে সেটি আসলে কোন ব্যবহারকারী হিসেবে চলছে তা যাচাই করা জরুরি। কারণ এর ডাটাবেস ধারণকারী ডিরেক্টরি সেই ব্যবহারকারীর মালিকানাই গ্রহণ করবে, আপনি PUID সেট করুন বা না করুন। একটি রিমোট অ্যাক্সেস রিলে একই ক্যাটাগরিতে পড়ে, তাই যখন আপনি নিজের RustDesk relay server চালান, তখন hbbs প্রথমবার চালু হওয়ার সময় যে Ed25519 কী পেয়ার তৈরি করে তা আপনার bind mount-এ সেই ব্যবহারকারীর মালিকানায় থাকে যে ব্যবহারকারী হিসেবে ইমেজটি শেষ হয়েছে, এবং হোস্ট সাইডের chown হলো আপনার জন্য একমাত্র সংশোধনমূলক ব্যবস্থা। পরবর্তীতে যুক্ত করা অবকাঠামোর ক্ষেত্রেও একই নিয়ম প্রযোজ্য, তাই আপনার অ্যাপগুলোর সামনে Authentik বসিয়ে সিঙ্গেল লগইন সুবিধা পাওয়ার অর্থ হলো এমন অফিসিয়াল সার্ভার, Postgres এবং Redis ইমেজ চালানো যা কোনো PUID পড়ে না, এবং তাদের ভলিউমের মালিকানা কনফিগারযোগ্য কোনো এন্ট্রি পয়েন্টের পরিবর্তে রানটাইম থেকে নির্ধারিত হয়।

তাই প্রজেক্টগুলোর মধ্যে এনভায়রনমেন্ট ব্লক কপি করার আগে প্রতিটি ইমেজের README ফাইল চেক করুন। Docker আপনার সেট করা যেকোনো এনভায়রনমেন্ট ভেরিয়েবল কন্টেইনারের ভেতর পাঠিয়ে দেয়, তা সেটি কোনো কিছু দ্বারা পঠিত হোক বা না হোক। একটি PUID যা কোনো কিছু ব্যবহার করে না, তা কোনো এরর বা ওয়ার্নিং তৈরি করে না এবং এর কোনো প্রভাবও নেই। কন্টেইনারটি তার নিজস্ব Dockerfile-এ নির্ধারিত ব্যবহারকারী হিসেবেই চলে এবং এটি যে ফাইলগুলো তৈরি করে তার মালিকানা দেখলেই আপনি তা বুঝতে পারবেন। নতুন কিছু বক্সে যোগ করার আগেই এই বিষয়টি পড়ে নিন, যার মধ্যে একটি self-hosted open-kritt security scanning stack অন্তর্ভুক্ত। এখানে Compose ফাইলটি আপনাকে জানিয়ে দেবে যে ইমেজগুলো PUID সমর্থন করে কি না, অথবা আপনার মাউন্ট করা ডিরেক্টরির মালিকানা ইমেজগুলো নিজেই নির্ধারণ করে দেয় কি না।

FAQ

আমার Docker ফাইলগুলোর মালিকানা কেন 911:911 দেখাচ্ছে?

911 হলো linuxserver.io ইমেজগুলোতে বিল্ট-ইন থাকা abc ব্যবহারকারীর UID এবং GID। এটি দেখার অর্থ হলো কন্টেইনারটি PUID এবং PGID সেট না করেই চালু হয়েছে, তাই এর init স্ক্রিপ্ট বিল্ট-ইন ডিফল্ট মানগুলোই রেখে দিয়েছে। ls -l কাঁচা সংখ্যাগুলো দেখায় কারণ আপনার হোস্ট মেশিনে 911 আইডি সম্বলিত কোনো অ্যাকাউন্ট নেই, তাই দেখানোর মতো কোনো নাম নেই। PUID এবং PGID-এ id-এর আউটপুট সেট করুন, docker compose up -d দিয়ে কন্টেইনারটি পুনরায় তৈরি করুন এবং তারপর আক্রান্ত ডিরেক্টরিতে sudo chown -R 1000:1000 চালিয়ে ফাইলগুলোর মালিকানা ঠিক করুন।

PUID এবং PGID কি সব Docker ইমেজে কাজ করে?

না। এগুলো কোনো Docker ফিচার নয় এবং Docker এগুলো কখনোই পড়ে না। এগুলো শুধুমাত্র সেই ইমেজগুলোতে কাজ করে যেগুলোর এন্ট্রি পয়েন্ট এগুলো পড়ে এবং অ্যাপ্লিকেশন শুরুর আগে usermod ও groupmod কল করে; linuxserver.io ফ্যামিলি এবং এই প্যাটার্ন অনুসরণ করা কিছু প্রজেক্টে এটি দেখা যায়। অন্যান্য প্রজেক্ট ভিন্ন নাম ব্যবহার করে, যেমন paperless-ngx-এ USERMAP_UID এবং USERMAP_GID। যে ইমেজে এগুলো কোনটিই পড়ে না, সেখানে ভেরিয়েবলগুলো গ্রহণ করা হয় কিন্তু কোনো সতর্কতা ছাড়াই উপেক্ষা করা হয়।

আমার কি PUID এবং PGID ব্যবহার করা উচিত নাকি Docker Compose-এ user: কি (key) ব্যবহার করা উচিত?

যখন ইমেজ এগুলো সাপোর্ট করে তখন PUID এবং PGID ব্যবহার করুন, কারণ এন্ট্রি পয়েন্টটি রুট হিসেবে ততক্ষণই চলে যতক্ষণ না /config ঠিক করা এবং সার্ভিসগুলো সঠিকভাবে শুরু করা হয়। যখন ইমেজে PUID সাপোর্ট নেই, অথবা ইমেজের README-তে যদি উল্লেখ থাকে যে এটি নন-রুট অপারেশনের জন্য পরীক্ষিত, তখন user: ব্যবহার করুন। linuxserver ইমেজে user: সেট করলে PUID এবং PGID নিষ্ক্রিয় হয়ে যায়, Docker Mods এবং কাস্টম সার্ভিসগুলো চলা বন্ধ হয়ে যায় এবং প্রতিটি মাউন্ট করা ভলিউমের পারমিশনের দায়িত্ব আপনার ওপর বর্তায়।

Sonarr-এ সঠিক PUID থাকা সত্ত্বেও ফাইল সরাতে পারছে না। সমস্যা কোথায়?

পর্যায়ক্রমে তিনটি বিষয় পরীক্ষা করুন। প্রথমত, মিডিয়া মাউন্ট নিজে: init শুধুমাত্র /app, /config এবং /defaults-এর মালিকানা পরিবর্তন (chown) করে, তাই /data বা /downloads হোস্ট মেশিনে যে মালিকানায় আছে সেটিই থেকে যায়। দ্বিতীয়ত, শেয়ার্ড গ্রুপ: যদি ডাউনলোড ক্লায়েন্ট এবং Sonarr ভিন্ন GID-তে চলে, তবে কেউ অন্যের ফাইল পরিবর্তন করতে পারবে না, তাই স্ট্যাকের প্রতিটি কন্টেইনারকে একই PGID দিন। তৃতীয়ত, umask: ইমেজের ডিফল্ট UMASK=022 ফাইলগুলোকে 0644 হিসেবে লেখে যাতে গ্রুপ রাইট বিট থাকে না, যা শেয়ার্ড গ্রুপের কার্যকারিতা নষ্ট করে। UMASK=002 সেট করুন এবং ডিরেক্টরিগুলোতে chmod 2775 দিয়ে setgid বিট সেট করুন যাতে নতুন ফাইলগুলো গ্রুপ উত্তরাধিকারসূত্রে পায়।