SSD Nodes Learn Hosting plans →
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-09-04

تثبيت Docker على Rocky Linux وAlmaLinux

ثبّت Docker Engine عبر dnf في أربع أوامر، ثم أصلح خطأ تعارض Podman على الأمر docker ومشكلة SELinux مع bind mounts التي تتجاهلها أدلة Ubuntu.

تثبيت Docker على Rocky Linux وAlmaLinux

لتثبيت Docker على Rocky Linux أو AlmaLinux، أضف مستودع dnf الخاص بـDocker، وثبّت المحرك مع compose plugin، ثم فعّل الخدمة. يتطلب ذلك أربعة أوامر، والخطوات متطابقة في التوزيعتين لأن كلتيهما إعادة بناء لـRed Hat Enterprise Linux (RHEL) وتشتركان في تخطيط الحزم نفسه. ويعمل CentOS Stream بالطريقة نفسها. تنطبق جميع الخطوات أدناه على التوزيعتين، لذلك إذا كنت لا تزال تختار بينهما، فإن العاملين الحاسمين هما ضمان التوافق الذي يقدمه كل مشروع وما إذا كان المعالج الأقدم لديك لا يزال مدعوماً.

التثبيت مختصر، لذلك يركّز معظم هذا الدليل على الاختلافات التي يفرضها Enterprise Linux (EL) مقارنةً بـUbuntu. قد يكون Podman قد سجّل الأمر docker على صورتك. يمنع SELinux الملفات المربوطة عبر bind mount إلى أن تحمل التصنيف الصحيح. لا يرشّح Firewalld المنافذ التي ينشرها Docker، لذلك قد يكون منفذ حاوية مفتوحاً على الإنترنت بينما يبلغ firewall-cmd عن عدم وجود أي منفذ مفتوح.

لا تستخدم برنامج Docker النصي الميسّر من get.docker.com. تنص وثائق Docker نفسها على أنه غير موصى به في بيئات الإنتاج. فهو يعيد كتابة إعدادات المستودع دون طلب تأكيد، ولا يمكن تشغيله مرة أخرى بأمان لإجراء ترقية. تعني إضافة المستودع يدوياً أن dnf upgrade يعامل Docker مثل أي حزمة أخرى على الخادم. كما يجعل ذلك المحرك مشمولاً في نطاق dnf-automatic، إذا كنت تستخدمه لتطبيق تحديثات الأمان وفق جدول زمني، لذلك قرّر مبكراً ما إذا كنت تريد تصحيح Docker تلقائياً أو تأجيل ذلك إلى نافذة صيانة. في كلتا الحالتين، تستبدل الترقية الملف التنفيذي المضمّن بينما يواصل dockerd القديم عمله، ويخبرك needs-restarting بالخدمات التي لا تزال تشغّل الشيفرة التي استبدلتها للتو.

هل يجيب podman عن أمر docker بالفعل؟

تأتي Rocky Linux وAlmaLinux مع podman في مستودعاتهما الافتراضية، وتثبّته كثير من صور VPS نيابةً عنك. تذهب بعض الصور إلى أبعد من ذلك وتثبّت podman-docker، الذي يضع برنامج shell النصي في /usr/bin/docker ويستدعي podman. لذلك ينفّذ podman كل أمر docker تكتبه، ويبدأ الدليل المكتوب لـ Docker بإنتاج مخرجات لم تكن تتوقعها.

أول مؤشر هو رسالة ترويسة. يتحقق البرنامج النصي /usr/bin/docker من وجود الملف /etc/containers/nodocker، وعندما يكون الملف مفقوداً يطبع سطراً واحداً قبل تنفيذ أي شيء:

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

قد يكون أحدهم قد أنشأ ذلك الملف لإخفاء الرسالة، لذلك لا تعتمد عليه وحده. اسأل قاعدة بيانات الحزم عن الحزمة التي تملك الملف التنفيذي:

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

تعني الإجابة التي تبدأ بـ podman-docker أن podman هو الذي يجيب. وتعني الإجابة التي تبدأ بـ docker-ce-cli أن Docker الحقيقي هو المستخدم. إذا أبلغ rpm -qf عن عدم وجود حزمة تملك الملف، فهذا يعني أن أحدهم ثبّته يدوياً، وعليك قراءة البرنامج النصي قبل الوثوق به.

يشغّل Podman صور OCI نفسها، وهو خيار معقول. إذا كنت تريده، فتوقف هنا. كلاهما محرّك حاويات لنظام Linux، لذلك إذا كان اختيار المنصة لا يزال مفتوحاً، فمن المفيد معرفة أن تعزل FreeBSD jails مساحة مستخدم كاملة بدلاً من تشغيل صور ذات طبقات تُسحب من سجل. إذا كنت تريد Docker Engine، فأزل الحزم المتعارضة أولاً. هذه هي القائمة التي توثقها Docker لنظام RHEL:

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

اقرأ ما يخطط dnf لإزالته معها قبل التأكيد. تكون القائمة قصيرة في صورة VPS جديدة. أما على خادم استخدمه أحدهم من قبل، فقد تؤدي إزالة podman إلى إزالة cockpit-podman أو أداة أخرى تعتمد عليها.

من الممكن نظرياً إبقاء podman إلى جانب Docker: أزل podman-docker فقط كي يصبح الاسم docker متاحاً، وأزل runc الذي تستبدله الحزمة containerd.io. تتعامل وثائق Docker مع podman باعتباره حزمة متعارضة، ولذلك لا تدعم Docker هذا الترتيب. إذا استمر التثبيت في الإبلاغ عن تعارض، فاستخدم قائمة الإزالة الكاملة أعلاه.

إضافة مستودع Docker باستخدام dnf config-manager

تنشر Docker حزم RPM لأنظمة Enterprise Linux في download.docker.com. يشير ملف المستودع إلى شجرة CentOS، وهي الشجرة التي تستخدمها Rocky Linux وAlmaLinux. قد يبدو توجيه نظام Rocky إلى مستودع CentOS خطأً، إلى أن تعرف كيف نشأ التوزيعان من سلالة CentOS بعد أن حوّلت Red Hat نظام CentOS إلى Stream في 2020. وفق التحقق الذي أُجري في August 2026، توثّق Docker هذا المستودع لـ CentOS Stream 9 وCentOS Stream 10.

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

أزال الإصدار 5 من dnf الوسيط --add-repo، لذلك يفشل الأمر الثاني في الإصدارات الأحدث. تحقّق من الإصدار الموجود لديك، ثم اختر الصيغة المطابقة:

dnf --version

إذا طبع الإصدار 5.x، فاستخدم صيغة الأمر الفرعي بدلاً من ذلك:

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

يكتب كلا الأمرين الملف نفسه في /etc/yum.repos.d/docker-ce.repo. تفشل الصيغة الخاطئة بسبب وسيط غير معروف، بدلاً من تنفيذ شيء خاطئ بصمت، لذلك ستلاحظ المشكلة.

يعيّن ملف المستودع ذلك baseurl إلى مسار يحتوي على $releasever، ويستبدل dnf قيمة هذا المتغير من حزمة الإصدار لديك. تعيّنه Rocky Linux وAlmaLinux إلى رقم الإصدار الرئيسي، لذلك تكون القيمة 9 على EL 9 و10 على EL 10. لهذا السبب يُحل مستودع CentOS بشكل صحيح على نظام Rocky. أكّد قيمة المتغير قبل التثبيت:

sudo dnf repoinfo docker-ce-stable

اقرأ السطر Repo-baseurl. يجب أن ينتهي بـ /9/x86_64/stable أو /10/x86_64/stable. إذا عيّن إصدارك $releasever إلى إصدار فرعي مثل 9.6، فسيعرض dnf الخطأ Status code: 404 لهذا الرابط عند جلب البيانات الوصفية. أصلح ذلك بتحرير /etc/yum.repos.d/docker-ce.repo واستبدال $releasever بالرقم الرئيسي فقط.

تثبيت المحرك وملحق Compose

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

هناك خمس حزم، ولكل حزمة وظيفة واحدة. docker-ce هو البرنامج الخدمي، وdockerd. docker-ce-cli هو الأمر docker الذي تكتبه. containerd.io هو وقت تشغيل الحاويات الذي يتحكم فيه البرنامج الخدمي. docker-buildx-plugin ينشئ الصور. docker-compose-plugin يوفّر docker compose كأمر فرعي.

لا تثبّت هذه الحزم ملفاً تنفيذياً باسم docker-compose يحتوي على واصلة. كان ذلك خاصاً بـCompose v1، الذي انتهى عمره الافتراضي في July 2023. يجب تحديث أي شيء يستدعي docker-compose مع واصلة إلى docker compose مع مسافة.

يتوقف التثبيت الأول لاستيراد مفتاح توقيع Docker ويعرض بصمته. يأتي المفتاح من gpgkey=https://download.docker.com/linux/centos/gpg في ملف المستودع الذي أضفته للتو، لذلك قارن البصمة التي يطبعها dnf مع عنوان URL هذا قبل قبول المفتاح.

يظهر أحد الأخطاء كثيراً بما يكفي لتسميته. إذا أبلغ dnf بأن containerd.io يتطلب container-selinux، ولم يوفّر أي شيء هذه الحزمة، فهذا يعني أن مستودع AppStream معطّل. شغّل dnf repolist وتأكد من إدراج appstream، لأن container-selinux يُطرح من خلاله في EL 9 وEL 10.

بدء Docker والتحقق من تشغيله

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

تترك حزم RPM الخاصة بـDocker البرنامج الخفي متوقفاً ومعطلاً بعد التثبيت. لذلك تظهر هذه الخطوة في صفحة Docker الخاصة بـCentOS ولا تظهر في صفحة Ubuntu، حيث يبدأ ملف deb الخدمة نيابةً عنك. تخطَّ enable، وسيعمل Docker حتى إعادة التشغيل التالية، ثم يبقى متوقفاً ويوقف معه كل حاوية.

يجب أن يعرض systemctl status القيمة Active: active (running). يجب أن تطبع الحاوية hello-world القيمة This message shows that your installation appears to be working correctly. ثم تنتهي. إذا طبعت بدلاً من ذلك خطأ صلاحيات على /var/run/docker.sock، فهذا يعني أنك حذفت sudo، ويعالج قسم مجموعة docker أدناه هذه المشكلة.

تحقق من compose plugin بشكل منفصل، لأنه حزمة مختلفة وقد يكون مفقوداً رغم أن المحرك يعمل:

docker compose version

تبدو النتيجة السليمة مثل Docker Compose version v2.x.x. استعادة خدماتك بعد إعادة التشغيل مسألة منفصلة عن تمكين البرنامج الخفي، وتحدد سياسات إعادة التشغيل ما إذا كانت خدمات Compose ستعود عند الإقلاع.

لماذا يؤدي bind mount إلى رفض الإذن؟

تشغّل Rocky Linux وAlmaLinux ‏SELinux (Security-Enhanced Linux) في وضع enforcing افتراضياً. أكّد ذلك باستخدام getenforce، الذي يطبع Enforcing.

تعمل حاويات Docker ضمن نوع SELinux ‏container_t، ولا يسمح لها هذا النوع إلا بقراءة الملفات ذات الوسم container_file_t وكتابتها. يحمل الدليل الذي أنشأته على المضيف الوسم الذي يمنحه له مساره الأب، وهذا الوسم ليس container_file_t. يرفض النظام وصول الحاوية رغم أن المالك والمجموعة ونمط الأذونات تبدو صحيحة من جهة المضيف. أعد إنتاج المشكلة باستخدام 3 أوامر:

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

تطبع الحاوية:

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

يوضح أمران السبب. يطبع ls -ldZ /srv/site الوسم، ويكون المسار الموجود ضمن /srv ذا الوسم system_u:object_r:var_t:s0، وليس container_file_t. ثم يطبع sudo ausearch -m avc -ts recent سجل التدقيق الخاص بالنواة، ويتضمن avc: denied { read }، وهو حقل scontext= يسمّي container_t، وحقل tcontext= يسمّي الوسم الذي رأيته للتو على الدليل. عدم التطابق بين هذين الحقلين يفسّر المشكلة بالكامل.

الإصلاح هو إضافة لاحقة إلى وسيط volume. يعيد Docker وسم المسار نيابةً عنك:

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

تعيد :z بالأحرف الصغيرة وسم المحتوى باعتباره مشتركاً، لذلك يمكن لعدة حاويات استخدام الدليل نفسه. أما :Z بالأحرف الكبيرة فتعيد وسمه باعتباره خاصاً وغير مشترك، وتربطه بحاوية واحدة؛ عندها تُرفض حاوية ثانية تحاول قراءة المسار نفسه. استخدم :z لأي شيء تصل إليه أيضاً sidecar أو حاوية النسخ الاحتياطي. استخدم :Z لدليل قاعدة بيانات تملكه حاوية واحدة.

تتضمن وثائق Docker تحذيراً يستحق التكرار، لأن إعادة الوسم ت recursive. يؤدي ربط دليل نظام مثل /home أو /usr باستخدام :Z إلى "جعل جهاز المضيف غير قابل للتشغيل، وقد تحتاج إلى إعادة وسم ملفات جهاز المضيف يدوياً". وجّه هذه اللاحقات إلى الأدلة التي أنشأتها للحاوية، ولا تستخدمها أبداً مع مسار نظام.

في Compose، تُضاف اللاحقة إلى السلسلة نفسها:

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

هناك حدّان يسهل الاصطدام بهما. لا يستطيع الخيار --mount تعيين وسم SELinux إطلاقاً، لذلك استخدم -v عند الحاجة إلى وسم. ولا تحتاج named volumes إلى لاحقة، لأن Docker يوسم الأدلة التي ينشئها ضمن /var/lib/docker/volumes بنفسه.

لا تعطل SELinux. استخدم sudo setenforce 0 لمدة دقيقة واحدة فقط للاختبار: إذا عملت الحاوية بعد ذلك، فالمشكلة متعلقة بوسم، ويكون :z هو الحل. أعد تفعيله باستخدام sudo setenforce 1 فوراً. في Enterprise Linux، توجد حالتان منفصلتان لـpermission denied على bind mount، لكنهما تبدوان متطابقتين من داخل الحاوية. الأولى هي وسم SELinux. والثانية هي ملكية المستخدم والمجموعة الرقمية المعتادة، وهي المشكلة التي صُممت متغيرات PUID وPGID لحلها. يعرض ls -lnZ النمط والمالك الرقمي والوسم في سطر واحد، لتتمكن من تحديد المشكلة التي تواجهها.

لماذا يمكن الوصول إلى منفذ منشور رغم أن firewalld يبدو مغلقاً؟

firewalld هو الجدار الناري الافتراضي في Rocky Linux وAlmaLinux. تحقّق من تشغيله باستخدام sudo systemctl is-active firewalld. إذا لم تكن قد أعددته على هذا الخادم بعد، فابدأ بـفتح منفذ SSH ومنفذ ويب باستخدام firewalld، لأن المفاجأة التالية لا تصبح مفهومة إلا بعد وجود مجموعة قواعد منطقة عاملة يمكن مقارنتها بها. انشر الآن منفذاً وتحقّق مما يراه firewalld مفتوحاً:

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

يطبع firewall-cmd سطراً فارغاً. ومن جهاز آخر، يعرض curl -I http://YOUR_SERVER_IP:8080/ النتيجة HTTP/1.1 200 OK. المنفذ مفتوح على الإنترنت، بينما لا يعرض جدارك الناري أي شيء.

السبب هو المسار الذي تسلكه الحزمة. ترشّح قواعد مناطق firewalld حركة المرور الموجّهة إلى الخادم نفسه. أما المنفذ المنشور فلا يكون موجّهاً إلى الخادم: إذ يثبّت Docker قاعدة destination NAT (ترجمة عنوان الشبكة) تعيد كتابة الوجهة إلى عنوان الحاوية قبل وصول الحزمة إلى مسار الإدخال في الخادم، لذلك يمرّر kernel الحزمة بدلاً من تسليمها محلياً. ثم يضع Docker واجهات الجسر الخاصة به في منطقة firewalld المسماة docker، والتي يكون هدفها ACCEPT، ويضيف سياسة تمرير مسماة docker-forwarding تسمح بالتمرير من أي منطقة إلى منطقة docker. لذلك لا ترى قواعد منطقتك الحزمة.

أبسط حل لا يحتاج إلى قاعدة جدار ناري. اربط جانب الخادم من النشر بواجهة loopback وضع 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، ولا يعود الطلب نفسه من جهاز آخر متصلاً. أي منفذ لا يحتوي على عنوان الخادم في الوسيطة -p يُنشر على كل واجهة، لذلك اعتبر كتابة -p 8080:80 وحدها قراراً بتعريض تلك الخدمة للعامة.

عندما تحتاج إلى إتاحة خدمة لعناوين معينة ومنعها عن عناوين أخرى، يحجز Docker سلسلة قواعد لهذا الغرض. تُعالَج DOCKER-USER قبل قواعد القبول الخاصة بـDocker، لذلك تبقى القاعدة التي تضعها هناك بعد إعادة تشغيل Docker وإعادة كتابة سلاسله:

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

استخرج اسم الواجهة من ip route show default بدلاً من افتراض eth0، لأن صور EL الحالية تستخدم أسماء مثل enp1s0 أو ens3. في Rocky وAlmaLinux، يُعد الأمر iptables طبقة توافق فوق nftables، وتظهر سلاسل Docker من خلاله. تختفي القواعد التي تضيفها بهذه الطريقة بعد إعادة التشغيل ما لم تحفظها، لذلك اكتبها في وحدة systemd بعد التأكد من ملاءمتها.

أغلق Docker Engine 28.0، الذي صدر في 2025، ثغرة مجاورة: إذ أصبح الوصول الموجّه مباشرة إلى منافذ الحاويات التي لم تُنشر محظوراً في سلسلة DOCKER. لا يؤثر هذا التغيير في المنافذ المنشورة، لذلك ما سبق ينطبق على الإصدارات الحالية. من المفيد اعتماد عادة تشغيلية واحدة: بعد أي sudo firewall-cmd --reload، اختبر المنفذ المنشور من جديد. إذا توقف عن الاستجابة، يعيد sudo systemctl restart docker تثبيت قواعد Docker.

يواجه مسؤولو Ubuntu المشكلة نفسها من خلال أداة مختلفة، وهي سبب تجاهل منافذ Docker المنشورة لقواعد ufw. مسار NAT هو السبب في الحالتين. الاختلاف الوحيد هو الجدار الناري الموجود أمامه.

إضافة مستخدم غير root إلى مجموعة docker

يصبح إدخال sudo قبل كل أمر docker مملاً، وتلغي مجموعة docker الحاجة إلى ذلك:

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

يعدّل usermod -aG ملف /etc/group، لكن shell الحالي يحتفظ بقائمة مجموعاته، لذلك لا يسري التغيير حتى تحصل على shell جديد. يبدأ newgrp docker shell مع إرفاق المجموعة به، حتى تتمكن من الاختبار فوراً. وتلتقط جلسات SSH الجديدة التغيير تلقائياً.

انتبه إلى الصلاحيات التي تمنحها هذه المجموعة. تمنح العضوية صلاحية الكتابة إلى /var/run/docker.sock، ويمكن لأي شيء يتصل بذلك socket أن يطلب من daemon بدء حاوية تربط نظام ملفات المضيف. يوضح أمر واحد معنى ذلك:

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

يقرأ هذا الأمر ملفاً لا يستطيع قراءته إلا root، من حساب لا يملك صلاحيات sudo. وتذكر وثائق Docker الخاصة بما بعد التثبيت الأمر نفسه: تمنح مجموعة docker صلاحيات مكافئة لصلاحيات root. أضف حساباً إليها فقط إذا كنت ستمنح ذلك الحساب sudo أيضاً. إذا كنت تعدّ حسابات على خادم جديد، فاحسم هذا الأمر مع بقية إعداد المستخدمين بأقل قدر من الصلاحيات على VPS، لا بعد ذلك.

يوفّر Docker أيضاً وضع rootless الذي يشغّل daemon كمستخدم غير مميّز. وهو مسار تثبيت منفصل، ويغيّر طريقة عمل برامج تشغيل التخزين والمنافذ الأقل من 1024، لذلك خطّط له كمشروع مستقل، لا كخيار تضيفه لاحقاً.

إلى أين تتابع

لديك الآن المحرك، وملحق Compose، وخدمة تستمر بعد إعادة التشغيل، وسلوكيات EL الثلاثة الخاصة الموثقة أعلاه. الخطوة التالية هي compose.yaml لكل خدمة، ويشرح تركيب ملف Compose تنسيق الملف والأوامر التي تديره. إذا كان هذا أول مضيف حاويات لك، فيغطي تشغيل Docker على VPS أسئلة تحديد الموارد والتخزين ونظافة الصور التي لا يتناولها هذا الدليل.

FAQ

هل يعمل مستودع Docker لـCentOS على Rocky Linux وAlmaLinux؟

نعم. أضف https://download.docker.com/linux/centos/docker-ce.repo مع dnf config-manager. يحتوي baseurl في ذلك الملف على $releasever، ويوسّعه Rocky Linux وAlmaLinux إلى رقم الإصدار الرئيسي، لذلك يحلّ خادم EL 9 إلى شجرة CentOS 9، وخادم EL 10 إلى شجرة CentOS 10. أكّد التوسعة باستخدام sudo dnf repoinfo docker-ce-stable واقرأ السطر Repo-baseurl. يشير ظهور Status code: 404 عند جلب dnf للبيانات الوصفية إلى أن المتغير توسّع إلى إصدار فرعي، ويؤدي تعديل /etc/yum.repos.d/docker-ce.repo لاستخدام الرقم الرئيسي المجرد إلى حل المشكلة.

هل يمكن تثبيت Docker وpodman على الخادم نفسه؟

تدرج وثائق Docker الحزمتين podman وrunc على أنهما متعارضتان، وتطلب إزالة كلتيهما قبل تثبيت Docker Engine. التعارض الفعلي هو حزمة podman-docker، التي تملك /usr/bin/docker وتحول كل أمر docker إلى أمر podman. نفّذ rpm -qf "$(command -v docker)" لمعرفة الحزمة التي تملك ذلك المسار. إذا بدأ الخرج بـpodman-docker، فإن podman هو الذي يستجيب. لا يدعم Docker تشغيل المحركين معاً، لذلك اختر أحدهما على الخادم الذي يعتمد عليه العمل.

لماذا يحصل الحاوي على خطأ permission denied عند استخدام bind mount؟

يكون SELinux في وضع enforcing افتراضياً على Rocky Linux وAlmaLinux. تعمل الحاويات بالنوع container_t، ولا يمكنها الوصول إلا إلى الملفات الموسومة بـcontainer_file_t، لذلك يحمل الدليل الذي أنشأته الوسم الخطأ ويُرفض الوصول إليه بصرف النظر عن مالكه ووضعه. أكّد ذلك باستخدام ls -ldZ على مسار المضيف، وsudo ausearch -m avc -ts recent الذي يطبع avc: denied مع سياقي الوصول المختلفين. أضف :z إلى وسيطة volume للمحتوى المشترك بين الحاويات، أو :Z للمحتوى الخاص بحاوية واحدة. لا توجّه :Z أبداً إلى /home أو /usr، لأن إعادة الوسم تكرارية وستؤدي إلى تعطيل المضيف.

هل أحتاج إلى فتح منفذ في firewalld لنشر منفذ حاوية؟

لا، وهذه هي المشكلة. تعيد قاعدة NAT في Docker كتابة عنوان الوجهة قبل وصول الحزمة إلى مسار الإدخال في المضيف، لذلك لا تفحصها قواعد المناطق في firewalld. كما يضع Docker جسوره في منطقة firewalld المسماة docker، مع الهدف ACCEPT. يمكن الوصول إلى حاوية بدأت باستخدام -p 8080:80 من الإنترنت، بينما لا يطبع sudo firewall-cmd --list-ports أي شيء. انشر المنفذ على عنوان محدد باستخدام -p 127.0.0.1:8080:80 عندما ينبغي للمضيف وحده الوصول إلى الخدمة، أو أدرج قواعد التصفية في السلسلة DOCKER-USER، التي يعالجها Docker قبل قواعد القبول الخاصة به.

هل إضافة المستخدم إلى مجموعة docker آمنة؟

إنها تمنح صلاحيات root. يستطيع عضو مجموعة docker الكتابة إلى /var/run/docker.sock، ثم يقرأ docker run --rm -v /:/host alpine wc -l /host/etc/shadow ملفاً لا يمكن الوصول إليه إلا من root باستخدام حساب لا يملك صلاحيات sudo. وتذكر وثائق Docker الخاصة بإجراءات ما بعد التثبيت التكافؤ نفسه. أضف فقط الحسابات التي كنت ستثق بها أصلاً مع sudo، واستمر في استخدام sudo docker للحسابات المشتركة أو حسابات الخدمات. يُعد Rootless mode البديل عند الحاجة إلى تشغيل الحاويات تحت مستخدم غير مميز، وهو مسار تثبيت منفصل وليس إعداداً.