SSD Nodes Learn Hosting plans →
تعلیمی Matt Connorتحریر: Matt Connor · اپ ڈیٹ شدہ 2026-09-04

Rocky Linux یا AlmaLinux پر Docker انسٹال کریں

dnf سے Docker Engine اور Compose plugin انسٹال کریں، پھر Ubuntu guides میں چھوڑی گئی رکاوٹیں حل کریں: docker command پر Podman کا قبضہ اور bind mounts میں SELinux۔

Rocky Linux اور AlmaLinux پر Docker انسٹال کریں

Rocky Linux یا AlmaLinux پر Docker انسٹال کرنے کے لیے Docker کی اپنی dnf repository شامل کریں، compose plugin کے ساتھ engine انسٹال کریں، پھر service فعال کریں۔ اس کے لیے چار commands درکار ہیں، اور دونوں distributions پر طریقہ یکساں ہے کیونکہ دونوں Red Hat Enterprise Linux (RHEL) کی rebuilds ہیں اور package layout مشترک رکھتی ہیں۔ CentOS Stream بھی اسی طرح کام کرتا ہے۔ ذیل کی تمام ہدایات دونوں پر لاگو ہوتی ہیں۔ اگر آپ ابھی دونوں میں انتخاب کر رہے ہیں تو فیصلہ کن عوامل ہر project کا کیا ہوا compatibility وعدہ اور آپ کے پرانے CPU کی موجودہ support ہیں۔

انسٹالیشن مختصر ہے، اس لیے اس guide کا زیادہ حصہ ان فرقوں پر مرکوز ہے جو Enterprise Linux (EL) میں Ubuntu کے مقابلے میں موجود ہیں۔ آپ کی image میں Podman پہلے ہی docker command استعمال کر رہا ہو سکتا ہے۔ SELinux bind-mounted files کو اس وقت تک block کرتا ہے جب تک ان پر درست label نہ ہو۔ Firewalld Docker کے published ports کو filter نہیں کرتا، اس لیے container port internet پر کھلا ہو سکتا ہے جبکہ firewall-cmd رپورٹ کرے کہ کچھ بھی open نہیں ہے۔

get.docker.com کی Docker convenience script استعمال نہ کریں۔ Docker کی اپنی documentation کے مطابق production کے لیے اس کی سفارش نہیں کی جاتی۔ یہ آپ سے پوچھے بغیر repository configuration دوبارہ لکھ دیتی ہے، اور upgrade کے لیے اسے محفوظ طریقے سے دوبارہ نہیں چلایا جا سکتا۔ Repository کو دستی طور پر شامل کرنے کا مطلب ہے کہ dnf upgrade Docker کو system کے ہر دوسرے package کی طرح manage کرتا ہے۔ اس سے engine dnf-automatic کے دائرۂ کار میں بھی آ جاتا ہے، اگر آپ اسے مقررہ وقت پر security updates لاگو کرنے کے لیے استعمال کرتے ہیں۔ اس لیے ابتدا ہی میں فیصلہ کریں کہ Docker کو unattended طور پر patch کرنا ہے یا maintenance window تک روک کر رکھنا ہے۔ دونوں صورتوں میں upgrade packaged binary کو تبدیل کر دیتا ہے، جبکہ پرانا dockerd چلتا رہتا ہے، اور needs-restarting وہ command ہے جو بتاتی ہے کہ کون سی services اب بھی وہ code چلا رہی ہیں جسے آپ نے ابھی تبدیل کیا ہے۔

کیا podman پہلے ہی docker کمانڈ کا جواب دے رہا ہے؟

Rocky Linux اور AlmaLinux اپنے default repositories میں podman فراہم کرتے ہیں، اور بہت سی VPS images اسے خود install کر دیتی ہیں۔ کچھ images اس سے بھی آگے بڑھ کر podman-docker install کرتی ہیں، جو /usr/bin/docker پر ایک shell script رکھتی ہے اور podman کو call کرتی ہے۔ آپ جو بھی docker command type کرتے ہیں، وہ podman چلاتی ہے۔ اس لیے Docker کے لیے لکھی گئی guide سے ایسا output آنا شروع ہو جاتا ہے جس کی آپ کو توقع نہیں تھی۔

پہلا اشارہ ایک banner ہوتا ہے۔ /usr/bin/docker script /etc/containers/nodocker file کی موجودگی check کرتی ہے۔ اگر یہ file موجود نہ ہو تو script کچھ بھی چلانے سے پہلے ایک سطر print کرتی ہے:

Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg.

ممکن ہے کسی نے banner خاموش کرنے کے لیے یہ file بنا دی ہو، اس لیے صرف اسی پر انحصار نہ کریں۔ Package database سے معلوم کریں کہ binary کس package کی ملکیت ہے:

command -v docker
rpm -qf "$(command -v docker)"

اگر جواب podman-docker سے شروع ہو تو podman جواب دے رہا ہے۔ اگر جواب docker-ce-cli سے شروع ہو تو اصل Docker موجود ہے۔ اگر rpm -qf رپورٹ کرے کہ کسی package کی اس file پر ملکیت نہیں ہے تو اسے کسی نے دستی طور پر install کیا ہے۔ ایسی صورت میں اس script پر اعتماد کرنے سے پہلے اسے پڑھیں۔

Podman وہی OCI images چلاتا ہے اور ایک مناسب انتخاب ہے۔ اگر آپ اسے استعمال کرنا چاہتے ہیں تو یہیں رک جائیں۔ دونوں Linux container engines ہیں۔ اگر platform کا فیصلہ ابھی باقی ہے تو یہ جاننا مفید ہے کہ FreeBSD jails registry سے حاصل کی گئی layered images چلانے کے بجائے مکمل userland کو isolate کرتی ہیں۔ اگر آپ Docker Engine چاہتے ہیں تو پہلے متصادم packages remove کریں۔ Docker نے RHEL کے لیے یہ فہرست document کی ہے:

sudo dnf remove docker docker-client docker-client-latest docker-common \
  docker-latest docker-latest-logrotate docker-logrotate docker-engine podman runc

تصدیق کرنے سے پہلے دیکھیں کہ dnf ان packages کے ساتھ کیا remove کرنے کا ارادہ رکھتا ہے۔ ایک تازہ VPS image پر فہرست مختصر ہوتی ہے۔ ایسے server پر جسے پہلے ہی استعمال کیا جا چکا ہو، podman remove کرنے سے cockpit-podman یا اس پر منحصر کوئی دوسرا tool بھی remove ہو سکتا ہے۔

اصولی طور پر podman کو Docker کے ساتھ رکھنا ممکن ہے: صرف podman-docker remove کریں تاکہ docker نام خالی ہو جائے، اور runc بھی remove کریں، جسے containerd.io package replace کرتا ہے۔ Docker کی documentation podman کو conflicting package سمجھتی ہے، اس لیے Docker اس layout کو support نہیں کرتا۔ اگر installation پھر بھی conflict رپورٹ کرے تو اوپر دی گئی مکمل removal list استعمال کریں۔

dnf config-manager کے ذریعے Docker کی repository شامل کریں

Docker Enterprise Linux کے لیے RPMs download.docker.com پر فراہم کرتا ہے۔ یہ repository file CentOS tree کی طرف اشارہ کرتی ہے، جس کے خلاف Rocky Linux اور AlmaLinux resolve ہوتے ہیں۔ Rocky system کو CentOS repository کی طرف point کرنا اس وقت تک غلطی معلوم ہوتا ہے جب تک آپ یہ نہ جانیں کہ Red Hat کی جانب سے 2020 میں CentOS کو Stream میں تبدیل کرنے کے بعد دونوں distributions کس طرح CentOS lineage سے وجود میں آئیں۔ August 2026 میں جانچ کے وقت Docker نے یہ repository CentOS Stream 9 اور CentOS Stream 10 کے لیے document کی تھی۔

sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

dnf version 5 نے --add-repo argument ختم کر دیا ہے، اس لیے نئی releases پر دوسری command fail ہو جاتی ہے۔ پہلے معلوم کریں کہ آپ کے پاس کون سا version ہے، پھر اسی کے مطابق form منتخب کریں:

dnf --version

اگر output میں 5.x version آئے تو subcommand form استعمال کریں:

sudo dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/centos/docker-ce.repo

دونوں commands ایک ہی file /etc/yum.repos.d/docker-ce.repo میں لکھتی ہیں۔ غلط form unknown-argument error کے ساتھ fail ہوتی ہے، خاموشی سے غلط کام نہیں کرتی، اس لیے یہ مسئلہ آپ سے پوشیدہ نہیں رہے گا۔

یہ repo file baseurl کو ایسی path پر set کرتی ہے جس میں $releasever شامل ہے، اور dnf اس variable کو آپ کے release package سے expand کرتا ہے۔ Rocky Linux اور AlmaLinux اسے major version number پر set کرتے ہیں۔ اسی لیے EL 9 پر 9 اور EL 10 پر 10 ہوتا ہے، اور Rocky system پر CentOS repository درست resolve ہوتی ہے۔ Install کرنے سے پہلے expansion کی تصدیق کریں:

sudo dnf repoinfo docker-ce-stable

Repo-baseurl line پڑھیں۔ اس کا اختتام /9/x86_64/stable یا /10/x86_64/stable پر ہونا چاہیے۔ اگر آپ کی release $releasever کو 9.6 جیسی point version پر set کرتی ہے تو dnf metadata fetch کرتے وقت اس URL کے لیے Status code: 404 report کرتا ہے۔ اسے درست کرنے کے لیے /etc/yum.repos.d/docker-ce.repo edit کریں اور $releasever کو صرف major number سے replace کریں۔

انجن اور compose پلگ اِن انسٹال کریں

sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

پانچ پیکیجز ہیں، اور ہر پیکیج ایک کام کرتا ہے۔ docker-ce daemon ہے، dockerd۔ docker-ce-cli وہ docker کمانڈ ہے جو آپ ٹائپ کرتے ہیں۔ containerd.io وہ container runtime ہے جسے daemon چلاتا ہے۔ docker-buildx-plugin images بناتا ہے۔ docker-compose-plugin بطور subcommand docker compose فراہم کرتا ہے۔

یہ پیکیجز hyphen والی docker-compose binary انسٹال نہیں کرتے۔ یہ Compose v1 تھا، جس کی سپورٹ July 2023 میں ختم ہو گئی۔ جو بھی چیز docker-compose کو hyphen کے ساتھ استعمال کرتی ہے، اسے space کے ساتھ docker compose میں تبدیل کرنا ضروری ہے۔

پہلی انسٹالیشن Docker کی signing key درآمد کرنے کے لیے رک جاتی ہے اور اس کا fingerprint دکھاتی ہے۔ یہ key اس repo file میں موجود gpgkey=https://download.docker.com/linux/centos/gpg سے حاصل ہوتی ہے جو آپ نے ابھی شامل کی ہے، اس لیے اسے قبول کرنے سے پہلے dnf کے دکھائے ہوئے fingerprint کا اس URL سے موازنہ کریں۔

ایک خرابی اتنی عام ہے کہ اسے الگ سے بیان کرنا ضروری ہے۔ اگر dnf رپورٹ کرے کہ containerd.io کے لیے container-selinux درکار ہے اور کوئی پیکیج اسے فراہم نہیں کرتا، تو آپ کا AppStream repository disabled ہے۔ `dnf repolist چلائیں اور تصدیق کریں کہ appstream فہرست میں موجود ہے، کیونکہ EL 9 اور EL 10 پر container-selinux` اسی repository سے دستیاب ہوتا ہے۔

Docker شروع کریں اور تصدیق کریں کہ یہ چل رہا ہے

sudo systemctl enable --now docker
sudo systemctl status docker --no-pager
sudo docker run --rm hello-world

Docker کے RPM packages installation کے بعد daemon کو stopped اور disabled چھوڑ دیتے ہیں۔ اسی لیے یہ step Docker کے CentOS page پر موجود ہے، Ubuntu page پر نہیں؛ وہاں deb آپ کی طرف سے service شروع کر دیتا ہے۔ enable کو چھوڑ دیں تو Docker اگلے reboot تک چلتا رہے گا، پھر بند ہو جائے گا اور اس کے ساتھ ہر container بھی بند ہو جائے گا۔

systemctl status میں Active: active (running) ظاہر ہونا چاہیے۔ hello-world container کو This message shows that your installation appears to be working correctly. print کرکے exit کرنا چاہیے۔ اگر اس کے بجائے /var/run/docker.sock پر permission error آئے تو آپ نے sudo شامل نہیں کیا۔ نیچے دیا گیا docker group section اس مسئلے کو حل کرتا ہے۔

compose plugin کو الگ سے check کریں، کیونکہ یہ مختلف package ہے اور engine درست ہونے کے باوجود missing ہو سکتا ہے:

docker compose version

صحت مند output Docker Compose version v2.x.x جیسا دکھائی دیتا ہے۔ reboot کے بعد اپنی services واپس لانا daemon کو enable کرنے سے الگ مسئلہ ہے، اور restart policies طے کرتی ہیں کہ Compose services boot پر واپس آتی ہیں یا نہیں۔

بائنڈ ماؤنٹ permission denied کیوں دیتا ہے؟

Rocky Linux اور AlmaLinux میں SELinux (Security-Enhanced Linux) بطورِ طے شدہ enforcing mode میں چلتا ہے۔ getenforce سے تصدیق کریں؛ یہ Enforcing دکھاتا ہے۔

Docker containers، SELinux type container_t کے تحت چلتے ہیں، اور یہ type صرف container_file_t کا label لگی ہوئی files کو پڑھ اور لکھ سکتا ہے۔ Host پر بنائی گئی directory کو اس کے parent path کا label ملتا ہے، جو container_file_t نہیں ہوتا۔ Host کی طرف سے owner، group اور mode درست نظر آنے کے باوجود container کو رسائی سے انکار کر دیا جاتا ہے۔ اسے تین commands سے دوبارہ پیدا کریں:

sudo mkdir -p /srv/site
echo hello | sudo tee /srv/site/index.html
sudo docker run --rm -v /srv/site:/usr/share/nginx/html:ro nginx:alpine cat /usr/share/nginx/html/index.html

Container یہ دکھاتا ہے:

cat: can't open '/usr/share/nginx/html/index.html': Permission denied

دو commands سے وجہ معلوم ہو جاتی ہے۔ ls -ldZ /srv/site label دکھاتا ہے۔ /srv کے تحت موجود path کے لیے یہ label system_u:object_r:var_t:s0 ہوتا ہے، container_file_t نہیں۔ پھر sudo ausearch -m avc -ts recent kernel کا audit record دکھاتا ہے۔ اس میں avc: denied { read } شامل ہوتا ہے، جو scontext= field ہے اور container_t کا نام بتاتا ہے، نیز tcontext= field directory پر موجود اس label کا نام بتاتا ہے جو آپ نے ابھی دیکھا ہے۔ ان دونوں fields میں عدم مطابقت ہی پوری وجہ ہے۔

حل volume argument کے آخر میں suffix لگانا ہے۔ Docker path کا label خود تبدیل کر دیتا ہے:

sudo docker run --rm -v /srv/site:/usr/share/nginx/html:ro,z nginx:alpine cat /usr/share/nginx/html/index.html

چھوٹے حروف والا :z content کو shared کے طور پر relabel کرتا ہے، اس لیے متعدد containers ایک ہی directory استعمال کر سکتے ہیں۔ بڑے حروف والا :Z اسے private اور unshared کے طور پر relabel کرتا ہے۔ یہ ایک container کے ساتھ مخصوص رہتا ہے، اور اسی path کو پڑھنے والے دوسرے container کو رسائی سے انکار کر دیا جاتا ہے۔ کسی sidecar یا backup container کے چھونے والی چیز کے لیے :z استعمال کریں۔ ایسی database directory کے لیے :Z استعمال کریں جس کی ملکیت ایک ہی container کے پاس ہو۔

Docker کی documentation میں ایک اہم warning دی گئی ہے، کیونکہ relabel recursive ہوتا ہے۔ :Z کے ساتھ /home یا /usr جیسی system directory کو bind-mount کرنا "آپ کی host machine کو ناقابلِ استعمال بنا دیتا ہے، اور آپ کو host machine کی files کا label دستی طور پر دوبارہ لگانا پڑ سکتا ہے"۔ ان suffixes کو صرف ان directories پر لگائیں جو آپ نے container کے لیے بنائی ہیں؛ انہیں کبھی system path پر نہ لگائیں۔

Compose میں suffix اسی string کے آخر میں لگتا ہے:

services:
  web:
    image: nginx:alpine
    volumes:
      - /srv/site:/usr/share/nginx/html:ro,z

دو حدود سے آسانی سے مسئلہ پیدا ہو سکتا ہے۔ --mount flag SELinux label بالکل set نہیں کر سکتا، اس لیے جب label درکار ہو تو -v استعمال کریں۔ Named volumes کو suffix کی ضرورت نہیں ہوتی، کیونکہ Docker /var/lib/docker/volumes کے تحت بنائی گئی directories کا label خود مقرر کرتا ہے۔

SELinux کو بند نہ کریں۔ صرف ایک منٹ کے test کے لیے sudo setenforce 0 استعمال کریں۔ اگر اس کے بعد container کام کرنے لگے تو مسئلہ label کا ہے اور :z اس کا حل ہے۔ فوراً sudo setenforce 1 کے ذریعے اسے دوبارہ فعال کریں۔ Enterprise Linux میں bind mount پر permission denied کی دو الگ وجوہات ہو سکتی ہیں، جو container کے اندر سے ایک جیسی نظر آتی ہیں۔ ایک وجہ SELinux label ہے۔ دوسری عام numeric user اور group ownership ہے، اور PUID اور PGID variables اسی مسئلے کے حل کے لیے موجود ہیں۔ ls -lnZ ایک ہی line میں mode، numeric owner اور label دکھاتا ہے، اس لیے آپ معلوم کر سکتے ہیں کہ مسئلہ کس چیز کا ہے۔

شائع کیا گیا port اس وقت قابلِ رسائی کیوں ہوتا ہے جب firewalld بند دکھائی دیتا ہے؟

Rocky Linux اور AlmaLinux میں firewalld ڈیفالٹ firewall ہے۔ sudo systemctl is-active firewalld سے تصدیق کریں کہ یہ چل رہا ہے۔ اگر آپ نے اس machine پر ابھی اسے configure نہیں کیا تو پہلے firewalld کے ذریعے SSH اور web port کھولیں، کیونکہ نیچے بیان کیا گیا مسئلہ اسی وقت سمجھ میں آتا ہے جب موازنہ کرنے کے لیے working zone ruleset موجود ہو۔ اب ایک port publish کریں اور دیکھیں کہ firewalld کے مطابق کیا open ہے:

sudo docker run -d --name web -p 8080:80 nginx:alpine
sudo firewall-cmd --list-ports

firewall-cmd ایک خالی لائن دکھاتا ہے۔ کسی دوسری machine سے curl -I http://YOUR_SERVER_IP:8080/، HTTP/1.1 200 OK واپس کرتا ہے۔ port internet کے لیے open ہے، لیکن آپ کا firewall کچھ بھی رپورٹ نہیں کر رہا۔

اس کی وجہ وہ path ہے جس سے packet گزرتا ہے۔ firewalld کے zone rules، host کو خود address کیے گئے traffic کو filter کرتے ہیں۔ Published port host کو address نہیں کرتا۔ Docker ایک destination NAT (network address translation) rule نصب کرتا ہے، جو packet کے host کے input path تک پہنچنے سے پہلے destination کو container کے address سے بدل دیتا ہے۔ اس لیے kernel packet کو مقامی طور پر deliver کرنے کے بجائے forward کرتا ہے۔ اس کے بعد Docker اپنے bridge interfaces کو firewalld کے docker نامی zone میں رکھتا ہے، جس کا target ACCEPT ہے، اور docker-forwarding نامی forwarding policy شامل کرتا ہے۔ یہ policy کسی بھی zone سے docker zone میں forwarding کی اجازت دیتی ہے۔ آپ کے zone rules اس packet کو دیکھ ہی نہیں پاتے۔

سب سے صاف حل کسی firewall rule کا محتاج نہیں۔ Host side کی publish کو loopback سے bind کریں اور اس کے سامنے reverse proxy رکھیں:

sudo docker rm -f web
sudo docker run -d --name web -p 127.0.0.1:8080:80 nginx:alpine
curl -I http://127.0.0.1:8080/

مقامی curl، HTTP/1.1 200 OK واپس کرتا ہے، جبکہ کسی دوسری machine سے وہی request اب connect نہیں ہوتی۔ -p argument میں host address نہ دینے پر service ہر interface پر publish ہو جاتی ہے۔ اس لیے bare -p 8080:80 کو اس service کو public طور پر expose کرنے کا فیصلہ سمجھیں۔

جب کسی service کو کچھ addresses سے قابلِ رسائی اور دوسروں سے ناقابلِ رسائی رکھنا ہو تو Docker آپ کے لیے ایک chain محفوظ رکھتا ہے۔ DOCKER-USER، Docker کے اپنے accept rules سے پہلے process ہوتا ہے۔ اس لیے وہاں شامل کیا گیا rule Docker کے restart ہونے اور اپنی chains دوبارہ لکھنے کے بعد بھی برقرار رہتا ہے:

sudo iptables -I DOCKER-USER -i enp1s0 ! -s 203.0.113.10 -j DROP
sudo iptables -S DOCKER-USER

Interface کا نام ip route show default سے لیں، eth0 فرض نہ کریں، کیونکہ موجودہ EL images میں enp1s0 یا ens3 جیسے نام استعمال ہوتے ہیں۔ Rocky اور AlmaLinux پر iptables command، nftables کے اوپر compatibility layer ہے، اور Docker کی chains اس کے ذریعے دکھائی دیتی ہیں۔ اس طریقے سے شامل کیے گئے rules reboot کے بعد ختم ہو جاتے ہیں، جب تک آپ انہیں save نہ کریں۔ اس لیے ان سے مطمئن ہونے کے بعد انہیں systemd unit میں لکھ دیں۔

2025 میں جاری ہونے والے Docker Engine 28.0 نے ایک متعلقہ مسئلہ حل کیا ہے۔ اب ان container ports تک direct routed access، جو کبھی publish نہیں کیے گئے، DOCKER chain میں block ہو جاتا ہے۔ اس تبدیلی کا published ports پر اثر نہیں پڑتا، اس لیے موجودہ versions پر بھی اوپر بیان کردہ تمام باتیں لاگو ہوتی ہیں۔ ایک عملی عادت اپنانا مفید ہے: کسی بھی sudo firewall-cmd --reload کے بعد published port کو دوبارہ test کریں۔ اگر اس نے جواب دینا بند کر دیا ہو تو sudo systemctl restart docker Docker کے rules دوبارہ نصب کرتا ہے۔

Ubuntu administrators کو یہی رکاوٹ ایک مختلف tool کے ذریعے پیش آتی ہے، جس کی وضاحت published Docker ports، ufw rules کو کیوں نظرانداز کرتے ہیں میں ہے۔ دونوں صورتوں میں وجہ NAT path ہے۔ فرق صرف اس firewall کا ہے جو اس path کے سامنے موجود ہے۔

غیر-root صارف کو docker گروپ میں شامل کرنا

ہر docker کمانڈ سے پہلے sudo لکھنا جلد ہی اکتا دینے والا ہو جاتا ہے، اور docker گروپ اس کی ضرورت ختم کر دیتا ہے:

sudo usermod -aG docker $USER
newgrp docker
docker run --rm hello-world

usermod -aG، /etc/group میں ترمیم کرتا ہے، لیکن موجودہ shell میں پہلے سے group list موجود ہوتی ہے، اس لیے یہ تبدیلی اس وقت تک لاگو نہیں ہوتی جب تک نئی shell نہ کھولی جائے۔ newgrp docker ایسی shell شروع کرتا ہے جس میں یہ گروپ شامل ہوتا ہے، تاکہ آپ فوراً جانچ کر سکیں۔ نئی SSH sessions خود بخود یہ تبدیلی حاصل کر لیتی ہیں۔

اس گروپ سے ملنے والی اجازت کو واضح طور پر سمجھیں۔ اس گروپ کی رکنیت /var/run/docker.sock تک write access دیتی ہے، اور جو بھی چیز اس socket سے رابطہ کر سکتی ہے، وہ daemon سے ایسی container شروع کرنے کو کہہ سکتی ہے جو host filesystem کو mount کرے۔ ایک کمانڈ اس کا مطلب دکھاتی ہے:

docker run --rm -v /:/host alpine wc -l /host/etc/shadow

یہ ایسی file پڑھتی ہے جسے صرف root پڑھ سکتا ہے، جبکہ account کے پاس sudo rights نہیں ہیں۔ Docker کی اپنی post-install documentation بھی یہی کہتی ہے: docker گروپ root کے مساوی privileges دیتا ہے۔ کسی account کو اس گروپ میں صرف اسی صورت شامل کریں جب آپ اسے sudo بھی دینے کے لیے تیار ہوں۔ اگر آپ نئے server پر accounts ترتیب دے رہے ہیں تو اس فیصلے کو بعد میں کرنے کے بجائے اپنے VPS پر کم سے کم مراعات والے user setup کے دیگر حصوں کے ساتھ ہی طے کریں۔

Docker ایک rootless mode بھی فراہم کرتا ہے، جس میں daemon غیر مراعات یافتہ user کے طور پر چلتا ہے۔ یہ الگ install path ہے، اور اس سے storage drivers اور 1024 سے کم ports کا طرزِ عمل تبدیل ہو جاتا ہے۔ اس لیے اسے بعد میں شامل کیے جانے والے flag کے بجائے الگ project کے طور پر plan کریں۔

اگلا مرحلہ

اب آپ کے پاس engine، compose plugin، reboot کے بعد برقرار رہنے والی service، اور اوپر درج EL سے متعلق تین رویے موجود ہیں۔ اگلا مرحلہ ہر service کے لیے compose.yaml ہے، جبکہ Compose file کا ڈھانچہ اس file format اور اسے چلانے والے commands کی وضاحت کرتا ہے۔ اگر یہ آپ کا پہلا container host ہے تو VPS پر Docker چلانا sizing، storage اور image hygiene سے متعلق ان سوالات کا احاطہ کرتا ہے جنہیں یہ guide شامل نہیں کرتی۔

FAQ

کیا Docker کی CentOS repository Rocky Linux اور AlmaLinux پر کام کرتی ہے؟

جی ہاں۔ https://download.docker.com/linux/centos/docker-ce.repo کو dnf config-manager کے ساتھ شامل کریں۔ اس فائل میں موجود baseurl میں $releasever شامل ہوتا ہے، اور Rocky Linux اور AlmaLinux اسے major version number میں تبدیل کرتے ہیں۔ اس لیے EL 9 سسٹم CentOS 9 tree اور EL 10 سسٹم CentOS 10 tree استعمال کرتا ہے۔ sudo dnf repoinfo docker-ce-stable سے اس expansion کی تصدیق کریں اور Repo-baseurl والی لائن پڑھیں۔ dnf کے metadata حاصل کرتے وقت Status code: 404 ظاہر ہو تو اس کا مطلب ہے کہ variable کو point release میں expand کیا گیا ہے۔ /etc/yum.repos.d/docker-ce.repo میں bare major number استعمال کرنے سے یہ مسئلہ حل ہو جاتا ہے۔

کیا Docker اور podman ایک ہی server پر انسٹال کیے جا سکتے ہیں؟

Docker کی documentation میں podman اور runc کو متصادم packages بتایا گیا ہے، اور Docker Engine انسٹال کرنے سے پہلے دونوں کو ہٹانے کی ہدایت دی گئی ہے۔ اصل تصادم podman-docker package کا ہے، جو /usr/bin/docker کا مالک ہے اور ہر docker command کو podman command میں تبدیل کر دیتا ہے۔ یہ دیکھنے کے لیے rpm -qf "$(command -v docker)" چلائیں کہ اس path کا مالک کون سا package ہے۔ اگر output podman-docker سے شروع ہو تو podman جواب دے رہا ہے۔ دونوں engines کو ساتھ رکھنا Docker کا supported layout نہیں ہے۔ اس لیے اہم server پر صرف ایک engine منتخب کریں۔

میرے container کو bind mount پر permission denied کیوں ملتا ہے؟

Rocky Linux اور AlmaLinux پر SELinux بطور default enforcing mode میں ہوتا ہے۔ Containers container_t type کے طور پر چلتے ہیں اور صرف container_file_t label والی files تک رسائی حاصل کر سکتے ہیں۔ اس لیے آپ کی بنائی ہوئی directory پر غلط label ہوتا ہے اور اس کے owner اور mode درست ہونے کے باوجود access denied ملتا ہے۔ Host path پر ls -ldZ اور sudo ausearch -m avc -ts recent سے تصدیق کریں۔ sudo ausearch -m avc -ts recent دو مختلف contexts کے ساتھ avc: denied دکھاتا ہے۔ Containers کے درمیان shared content کے لیے volume argument میں :z شامل کریں، یا صرف ایک container کے لیے private content پر :Z استعمال کریں۔ :Z کو کبھی /home یا /usr کی طرف point نہ کریں، کیونکہ relabel recursive ہوتا ہے اور host خراب کر دے گا۔

کیا container port publish کرنے کے لیے firewalld میں port کھولنا ضروری ہے؟

نہیں، اور یہی مسئلہ ہے۔ Docker کا NAT rule packet کے host کے input path تک پہنچنے سے پہلے destination address تبدیل کر دیتا ہے۔ اس لیے firewalld کے zone rules اس packet کا معائنہ نہیں کرتے۔ Docker اپنے bridges کو docker نامی firewalld zone میں بھی رکھتا ہے، جس کا target ACCEPT ہوتا ہے۔ -p 8080:80 کے ساتھ شروع کیا گیا container internet سے قابل رسائی ہوتا ہے، جبکہ sudo firewall-cmd --list-ports کچھ بھی ظاہر نہیں کرتا۔ جب صرف host کو service تک رسائی دینی ہو تو -p 127.0.0.1:8080:80 کے ذریعے اسے مخصوص address پر publish کریں، یا DOCKER-USER chain میں filtering rules شامل کریں۔ Docker اپنی accept rules سے پہلے اسی chain کو process کرتا ہے۔

کیا اپنے user کو docker group میں شامل کرنا محفوظ ہے؟

اس سے root access مل جاتا ہے۔ docker group کا رکن /var/run/docker.sock میں لکھ سکتا ہے، اور docker run --rm -v /:/host alpine wc -l /host/etc/shadow کے ذریعے ایسے account سے root-only file پڑھ سکتا ہے جسے sudo rights حاصل نہ ہوں۔ Docker کی post-install documentation بھی اسی equivalence کو بیان کرتی ہے۔ صرف ایسے accounts شامل کریں جنہیں آپ sudo کے برابر پہلے ہی trusted سمجھتے ہوں۔ Shared یا service accounts کے لیے sudo docker استعمال جاری رکھیں۔ جب unprivileged user کے تحت containers چلانے ہوں تو Rootless mode متبادل ہے۔ یہ setting نہیں بلکہ الگ install path ہے۔