الأدلة التقنية

تثبيت Portainer لإدارة حاويات Docker من المتصفح

إذا كنت تفضل الواجهة على سطر الأوامر، فإن Portainer يتيح لك إدارة الـ Containers من المتصفح. نثبته خطوة بخطوة، ونشغل منه أول تطبيق، ونضيف إليه خادماً ثانياً.

تثبيت Portainer لإدارة حاويات Docker من المتصفح

لنفرض أن لديك سيرفراً تعمل عليه عدة خدمات، وأردت أن تعرف ما الذي يعمل عليه الآن، أو أن تقرأ سجل Log لأحد ال Containers بعد أن توقف فجأة، فسوف تدخل عبر SSH وتفتح الطرفية Terminal وتبدأ في تذكر أوامر Docker واحداً تلو الآخر، وهذا مقبول عندما يكون السيرفر Server واحداً وأنت وحدك من يديره، ولكنه يصبح مرهقاً عندما تزيد الخدمات أو يشاركك فريق في الإدارة. وهنا يأتي دور Portainer CE، وهو واجهة ويب Web UI مفتوحة المصدر Open Source لإدارة Docker، حيث تعرض لك ال Containers وال Images والشبكات Networks وال Volumes في مكان واحد، وتقرأ منها السجلات، وتنشر منها ملفات Compose باسم Stacks، وتدير أكثر من سيرفر من نفس الواجهة.

وقد يتساءل البعض: لماذا نضيف واجهة فوق Docker طالما أن الأوامر تكفي؟ والإجابة أن Portainer يناسب الفريق الصغير الذي يريد أن يرى بسرعة ما يعمل على السيرفر دون أن يحفظ كل أوامر Docker، حيث يتيح الإصدار CE حسابات للمستخدمين وفرقاً Teams وتحديد صلاحيات Permissions الوصول إلى كل مورد، أما الأدوار التفصيلية RBAC وسجلات الدخول والنشاط Activity Logs التي يطلبها عادة مدير تقنية المعلومات IT Manager فهي في الإصدار التجاري Business Edition وحده. ولاحظ أن Portainer يصف الإصدار CE بأنه للمختبرات المنزلية Homelab والتعلم والبيئات غير الإنتاجية، ويقدمه دون دعم رسمي، لذلك إذا كان السيرفر يخدم أعمال مؤسستك فقدر ذلك قبل أن تعتمد عليه، أو جرب عرض Take 3 الذي يتيح Business Edition مجاناً على ثلاث عقد Nodes. وإذا كنت تدير كل شيء عبر Git وال CI فغالب الظن أنك لن تحتاج إليه، ويكفيك docker compose من الطرفية.

وسوف نناقش في هذا المقال ما يلي:

  • تثبيت Portainer CE بملف Compose وإصدار محدد، ولماذا لا نستخدم الوسم latest.
  • الإعداد الأول ورمز الإعداد setup token، ثم نشر أول Stack من الواجهة.
  • إدارة سيرفر ثان عبر Portainer Agent دون أن نفتح للمخترق باباً إلى السيرفر.
  • الوصول عبر نطاق وشهادة TLS، ثم التحقق والنسخ الاحتياطي والتحديث وأشهر المشكلات وحلولها.

ما تحتاجه قبل أن تبدأ Requirements

  • سيرفر عليه Docker Engine وCompose v2، وإذا لم يكن مثبتاً فابدأ بدليل تثبيت Docker على Ubuntu، وراجع متطلبات Portainer الرسمية.
  • الموارد Resources: يحتاج Portainer قرابة 30 ميجابايت من الذاكرة RAM، وال Agent قرابة 20 ميجابايت، ويزيد الاستهلاك كلما زاد عدد البيئات Environments والمستخدمين.
  • المنافذ Ports: المنفذ 9443/tcp لواجهة Portainer، وهو مؤقت حتى تضعها خلف Reverse Proxy، والمنفذ 9001/tcp على السيرفر الثاني إذا استخدمت Portainer Agent، ويكون عبر شبكة خاصة Private Network فقط كما سوف نوضح.
  • نطاق Domain مثل portainer.example.com للوصول عبر HTTPS بشهادة Certificate موثوقة Trusted، وهو اختياري ولكننا ننصح به.

تثبيت Portainer CE Installation

ستجد في أمثلة كثيرة على الإنترنت أن Portainer يثبت بأمر docker run واحد مع الوسم latest، والمشكلة في هذه الطريقة أن الإصدار سوف يتغير دون علمك عند أول docker compose pull، وقد تجد نفسك على إصدار جديد لم تقرأ ملاحظاته ولم تأخذ قبله نسخة احتياطية. لذلك نثبت الوسم Tag بالرقم الكامل، وليس latest ولا lts، والسبب أن Portainer يصدر في قناتين Channels: قناة LTS لبيئات الإنتاج Production وتستمر تحديثاتها الإصلاحية Patches مدة أطول، وقناة STS التي تحمل الميزات الجديدة، والإصدار Release 2.45.1 الذي نستخدمه هنا من قناة LTS. وتشرح صفحة التثبيت الرسمية على Linux هذه الخطوات بالتفصيل.

الآن سوف نقوم بإنشاء مجلد للخدمة نضع فيه ملف Compose واحداً:

sudo mkdir -p /opt/portainer
sudo chown $USER: /opt/portainer
cd /opt/portainer

ثم ننشئ الملف /opt/portainer/compose.yaml كما يلي:

services:
  portainer:
    image: portainer/portainer-ce:2.45.1
    container_name: portainer
    restart: unless-stopped
    ports:
      - "9443:9443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data

volumes:
  portainer_data:
    name: portainer_data

في الإعداد أعلاه لاحظ التالي:

  • المنفذ 9443 هو منفذ الواجهة عبر HTTPS بشهادة موقعة ذاتياً Self-signed ينشئها Portainer، أما المنفذ 8000 الذي تراه في أمثلة كثيرة فهو خاص بـ Edge Agent، فلا تنشره إذا لم تستخدمه.
  • السطر /var/run/docker.sock يمنح Portainer تحكماً كاملاً في Docker، والتحكم في Docker يعادل صلاحية root على السيرفر، وهذا يعني أن حساب المدير في Portainer يعادل root أيضاً، لذلك اختر له كلمة مرور قوية ولا تترك الواجهة مفتوحة للعامة.
  • سمينا ال Volume portainer_data صراحة حتى لا يضيف Compose اسم المشروع Project Name في أوله، وبالتالي يبقى الاسم ثابتاً في أوامر النسخ الاحتياطي Backup، وفي هذا ال Volume توجد قاعدة بيانات Database الخاصة بـ Portainer وملفات كل Stack تنشئه من الواجهة.
  • لا يوجد في الملف فحص صحة healthcheck، والسبب أن ال Image الخاصة بـ Portainer مبنية دون shell ودون curl، لذلك سوف نتحقق من الخدمة من الخارج عبر /api/system/status.
  • إذا وضعت Portainer خلف Reverse Proxy على نفس السيرفر، فاجعل سطر المنفذ "127.0.0.1:9443:9443" أو احذفه، كما سيأتي في قسم النطاق أدناه.

بعد ذلك شغل الخدمة وتابع السجل:

docker compose up -d
docker compose logs --tail 20 portainer

وعند تشغيل الأمر سوف تجد في السجل سطراً مثل starting HTTPS server | bind_address=:9443، وفوقه رمز الإعداد setup token، حيث تطلب الإصدارات الحديثة من Portainer هذا الرمز عند إنشاء حساب المدير Administrator الأول، والسبب أنه يمنع أي شخص آخر من أن يسبقك إلى هذه الشاشة إذا كان المنفذ مفتوحاً للعامة، ويلزمك أن تنشئ الحساب خلال 5 دقائق من تشغيل ال Container. استخرج الرمز بالأمر التالي:

docker logs portainer 2>&1 | grep setup_token

والمخرج سوف يكون كما يلي:

setup_token=5f68774697a97ee122d6ca1a19a4f60f9d4f9e11649bcf3943c507fa08eefbdf

أول دخول وإنشاء حساب المدير Initial Setup

افتح https://203.0.113.10:9443 بعد أن تضع عنوان سيرفرك مكانه، وسوف يحذرك المتصفح Browser من الشهادة الموقعة ذاتياً، وهذا متوقع في هذه المرحلة. اكتب اسم المدير وكلمة مرور Password من 12 حرفاً على الأقل، ثم الصق رمز الإعداد:

نموذج إنشاء حساب المدير الأول في Portainer مع حقل رمز الإعداد
إنشاء حساب المدير: كلمة مرور من 12 حرفاً على الأقل، ورمز الإعداد من سجل ال Container
⚠️
إذا تأخرت أكثر من 5 دقائق في إنشاء الحساب بعد تشغيل ال Container، فقد يعرض Portainer الرسالة timed out for security purposes، والحل أن تعيد تشغيل ال Container (docker compose restart portainer) ثم تستخرج رمز الإعداد الجديد من السجل وتكمل الخطوة فوراً، ولاحظ أن الرمز يتغير مع كل إعادة تشغيل، لذلك استخدم آخر سطر setup_token في السجل.

قد تظهر بعد ذلك صفحة عن Edge Compute، فتخطها بالزر Skip إذا لم تكن تدير أجهزة خلف NAT، ثم يظهر معالج Wizard البيئات وقد اكتشف Portainer المحرك المحلي Local Engine عبر ال socket:

معالج البيئات في Portainer مع خياري Get Started وAdd Environments
اختر Get Started لإدارة Docker على نفس السيرفر

اضغط Get Started ثم افتح البيئة local، وسوف ترى لوحة Dashboard البيئة التي تعرض عدد ال Stacks وال Containers وال Images وال Volumes والشبكات، ومنها تنتقل إلى أي قسم في القائمة الجانبية Sidebar:

لوحة البيئة المحلية في Portainer تعرض إصدار Docker وعدد الـ Containers والـ Images
لوحة البيئة المحلية: Standalone 29.8.1 عبر /var/run/docker.sock

نشر Stack من الواجهة

ال Stack في Portainer هو ملف Compose يحفظه Portainer ويشغله بـ docker compose، ولإنشاء واحد اختر Stacks من القائمة ثم Add stack، واكتب له اسماً، ثم الصق الملف في المحرر Editor. لنأخذ مثالاً بالتطبيق الصغير whoami الذي يعيد معلومات الطلب Request، وسوف نستخدمه لاحقاً في اختبار ال Reverse Proxy:

services:
  whoami:
    image: traefik/whoami:v1.11.0
    restart: unless-stopped
    ports:
      - "8081:80"
شاشة إنشاء Stack في Portainer مع محرر ملف Compose
محرر ال Stack: الاسم ثم محتوى ملف Compose

يمكنك إضافة متغيرات البيئة Environment Variables أسفل الصفحة، ويحفظها Portainer في stack.env، ولكن لاحظ أن هذه المتغيرات لا تصل إلى ال Container إلا إذا أشرت إليها في الملف بالصيغة ${VAR} أو بالسطر env_file: stack.env. بعد ذلك اضغط Deploy the stack، وخلال ثوان سوف تظهر صفحة ال Stack وفيها ال Containers وحالتها والمنافذ المنشورة، ومنها تصل إلى السجلات والطرفية والإحصاءات Stats لكل Container:

صفحة تفاصيل Stack في Portainer تعرض الـ Container whoami يعمل
ال Stack يعمل، والمنفذ 8081 منشور على السيرفر
💡
ال Stacks التي تنشئها بـ docker compose من الطرفية تظهر في Portainer مع العبارة This stack was created outside of Portainer، ويكون تحكمك فيها محدوداً بالتشغيل والإيقاف دون تعديل الملف، لذلك اختر لكل Stack طريقة واحدة، إما الطرفية وإما Portainer، ولا تجمع بينهما.

إدارة سيرفر ثان عبر Portainer Agent

عندما يصبح لديك سيرفران أو أكثر، فالحل الأول الذي يخطر على البال هو أن تثبت Portainer على كل سيرفر، وهذا يعني عدة واجهات وعدة حسابات مدير وعدة نسخ احتياطية، وهو حل غير مناسب. والحل الأنسب أن تثبت Docker على السيرفر الثاني بنفس الخطوات، وتشغل عليه Portainer Agent وحده، ثم تربطه بـ Portainer الأساسي.

في هذا النمط يبدأ Portainer الاتصال بال Agent على المنفذ 9001، لذلك يجب أن يصل السيرفر الأول إلى الثاني، والأفضل أن يمر هذا الاتصال عبر شبكة خاصة أو نفق Tunnel VPN مثل WireGuard، وتجد تفاصيله في دليل شبكة خاصة مع WireGuard وwg-easy.

أنشئ أولاً سراً مشتركاً Shared Secret بين الطرفين، وبعدها سوف يرفض ال Agent أي Portainer لا يحمل نفس السر:

openssl rand -hex 32

على السيرفر الثاني أنشئ الملف /opt/portainer-agent/compose.yaml، وضع مكان 10.8.0.2 عنوان السيرفر على الشبكة الخاصة، ثم ضع السر في ملف .env بجانبه بالصيغة AGENT_SECRET=...:

services:
  agent:
    image: portainer/agent:2.45.1
    container_name: portainer_agent
    restart: unless-stopped
    environment:
      AGENT_SECRET: ${AGENT_SECRET}
    ports:
      - "10.8.0.2:9001:9001"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/lib/docker/volumes:/var/lib/docker/volumes
      - /:/host
cd /opt/portainer-agent
docker compose up -d

الآن على السيرفر الأول أضف نفس السر إلى خدمة Portainer في /opt/portainer/compose.yaml، مع ملف .env بنفس القيمة، ثم أعد إنشاء ال Container:

    environment:
      AGENT_SECRET: ${AGENT_SECRET}
cd /opt/portainer
docker compose up -d

في Portainer افتح القسم Environment-related ثم Environments ثم Add environment، واختر Docker Standalone ثم Start Wizard، ثم Agent من More options، وسوف تعرض الشاشة أمر docker run المكافئ للملف أعلاه، وتطلب اسماً للبيئة وعنوان ال Agent بالصيغة IP:9001:

شاشة إضافة بيئة Docker Standalone عبر Agent مع أمر التشغيل وحقلي الاسم والعنوان
إضافة بيئة عبر Agent: الاسم وعنوان ال Agent على المنفذ 9001

اضغط Connect، فتظهر البيئتان في الصفحة الرئيسية، ولكل بيئة حالتها وعدد ال Containers فيها ونوع اتصالها:

الصفحة الرئيسية في Portainer تعرض بيئتين: local وserver2 عبر Agent
بيئتان في واجهة واحدة، ويظهر ال Agent هنا باسم ال Container agent على شبكة Docker، أما على سيرفراتك فسوف يظهر عنوان IP
🛑
يملك ال Agent صلاحية كاملة على Docker في سيرفره، بل وعلى نظام الملفات Filesystem أيضاً عبر /:/host، وهذا السطر لا يلزم إلا لميزات إدارة المضيف Host Management، فاحذفه إذا لم تحتج إليها. لذلك لا تنشر المنفذ 9001 على عنوان عام Public IP، وتذكر أن ufw لا يحجب منفذاً نشره Docker، وإنما انشره على عنوان الشبكة الخاصة كما في المثال، واستخدم AGENT_SECRET دائماً. وإذا لم تتوفر شبكة خاصة بين السيرفرين فاستخدم Edge Agent، والسبب أنه هو من يبادر بالاتصال بـ Portainer ولا يحتاج إلى منفذ وارد Inbound Port، وهو ما توصي به وثائق Portainer في أغلب الحالات.
📌
في مطلع 2024 رصد فريق Cado Security Labs حملة سماها Commando Cat تستهدف سيرفرات تركت Docker API مكشوفاً على الإنترنت، حيث يطلب المهاجم من Docker تشغيل Container يبدو بريئاً، ثم يخرج منه إلى نظام الملفات في السيرفر نفسه، فيضيف مفاتيح SSH لحساب root ومستخدماً مخفياً، ويسرق بيانات الدخول إلى AWS وGCP وAzure، ثم يشغل برنامج تعدين للعملات الرقمية. والدرس هنا أن أي منفذ يمنح التحكم في Docker، سواءً كان Docker API أو Portainer Agent، هو باب إلى السيرفر كله، فلا تتركه على عنوان عام.

الوصول عبر نطاق وشهادة TLS

المنفذ 9443 بشهادته الموقعة ذاتياً يصلح للدقائق الأولى فقط، أما في بيئة الإنتاج فضع Portainer خلف Reverse Proxy بنطاق مثل portainer.example.com وشهادة Let's Encrypt. وإذا كان Nginx Proxy Manager على نفس السيرفر، فأسهل طريقة أن تضع ال Containers الاثنين على شبكة Docker مشتركة، وبهذا الشكل لا تحتاج إلى نشر أي منفذ لـ Portainer:

docker network create proxy
services:
  portainer:
    image: portainer/portainer-ce:2.45.1
    container_name: portainer
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
    networks:
      - proxy

volumes:
  portainer_data:
    name: portainer_data

networks:
  proxy:
    external: true

في الإعداد أعلاه لاحظ أن قسم ports قد حذف بالكامل، وأن ال Container انضم إلى الشبكة proxy التي أنشأناها خارج الملف. بعد ذلك أضف نفس الشبكة proxy إلى ال Container الخاص بـ Nginx Proxy Manager، ثم أنشئ Proxy Host بالقيم التالية:

الحقلالقيمة
Domain Namesportainer.example.com
Schemehttps
Forward Hostname / IPportainer
Forward Port9443
Websockets Supportمفعل، وتحتاج إليه طرفية ال Containers وبث السجلات Log Streaming
SSLشهادة Let's Encrypt جديدة مع Force SSL

يتصل ال Reverse Proxy بـ Portainer داخلياً عبر HTTPS دون أن يتحقق من شهادته الموقعة ذاتياً، ثم يقدم للمتصفح شهادة Let's Encrypt. ولا تتخل عن Force SSL، والسبب أن Portainer يضع على ملفات تعريف الارتباط Cookies الخاصة بالدخول العلامة Secure عندما يتصل ال Reverse Proxy بالمنفذ 9443، ويرفضها المتصفح إذا فتحت الواجهة عبر http فيفشل الدخول. وبعد أن ينجح الدخول عبر النطاق أغلق أي منفذ باق لـ Portainer على العنوان العام، وللتفاصيل راجع دليل Portainer لتشغيله خلف nginx.

كيف تتأكد أن كل شيء يعمل؟ Verification

  • نفذ الطلب التالي على السيرفر للتأكد من أن Portainer يستجيب:
curl -sk https://127.0.0.1:9443/api/system/status

والمخرج سوف يكون كما يلي:

{"Version":"2.45.1","InstanceID":"..."}
  • تظهر البيئة local في واجهة Portainer بالحالة Status Up، وبيئة السيرفر الثاني بالحالة Up والنوع Agent.
  • إذا اختبرت المنفذ 9001 على العنوان العام للسيرفر الثاني من جهاز خارجي فيجب ألا يستجيب.

النسخ الاحتياطي والاستعادة Restore

أهم ما تنسخه هو ال Volume portainer_data، والسبب أن فيه المستخدمين والبيئات والإعدادات، وملفات ال Stacks التي أنشأتها من الواجهة في /data/compose، وانسخ معه محتوى /opt/portainer والملف /etc/docker/daemon.json. أما بيانات تطبيقاتك من قواعد بيانات وVolumes فلها نسخها الخاصة، وتجدها في دليل كل تطبيق.

أوقف Portainer لحظات حتى تحصل على نسخة متسقة Consistent من قاعدة بياناته، ثم قم بضغط Compress محتوى ال Volume في ملف واحد:

cd /opt/portainer
docker compose stop portainer
docker run --rm -v portainer_data:/data:ro -v "$PWD":/backup alpine:3.24 tar czf /backup/portainer-$(date +%F).tar.gz -C /data .
docker compose start portainer

ويمكنك كذلك تنزيل نسخة من الواجهة، حيث تفتح Settings ثم القسم Back up Portainer، وتختار Download backup file، وتفعل Password Protect لتشفير Encryption الملف، ثم تستعيد هذه النسخة لاحقاً من شاشة التثبيت الأولى (Restore Portainer from backup).

ولتستعيد من ملف tar على سيرفر جديد، ثبت Docker وانسخ /opt/portainer، ثم نفذ:

cd /opt/portainer
docker volume create portainer_data
docker run --rm -v portainer_data:/data -v "$PWD":/backup alpine:3.24 tar xzf /backup/portainer-2026-09-26.tar.gz -C /data
docker compose up -d

ثم انقل ملف النسخة إلى خارج السيرفر، إلى مخزن كائنات Object Storage أو سيرفر نسخ آخر، والسبب أن النسخة المحفوظة على نفس القرص لن تنفعك إذا فقدت القرص نفسه.

التحديث Upgrade إلى إصدار أحدث

  1. راجع صفحة الإصدارات، وابق على قناة LTS في بيئة الإنتاج.
  2. أنشئ نسخة احتياطية كما في القسم السابق.
  3. غير الوسم في compose.yaml وفي ملف ال Agent على كل سيرفر، والسبب أن إصدار ال Agents يجب أن يطابق إصدار Portainer دائماً.
  4. اسحب ال Image وأعد إنشاء ال Container بنفس ال Volume، كما تشرح صفحة التحديث الرسمية:
cd /opt/portainer
docker compose pull
docker compose up -d
docker compose logs --tail 20 portainer

والخطأ الشائع هنا أن تعيد إنشاء ال Container بـ Volume يحمل اسماً مختلفاً، فيبدأ Portainer من الصفر وتظهر ال Stacks القديمة كأنها أنشئت من خارجه ويصبح تحكمك فيها محدوداً، لذلك حافظ على نفس الاسم portainer_data في كل تحديث.

مشكلات شائعة وحلولها Troubleshooting

يعرض Portainer رسالة انتهاء المهلة Timeout عند الدخول الأول

أعد تشغيل ال Container ثم استخرج رمز الإعداد الجديد، أي نفذ docker compose restart portainer ثم docker logs portainer 2>&1 | grep setup_token | tail -n 1، والسبب في استخدام tail أن السجل يحتفظ بالرموز القديمة أيضاً.

Client sent an HTTP request to an HTTPS server

سوف ترى هذا الخطأ عندما تفتح http://...:9443، والسبب أن المنفذ 9443 يعمل بـ HTTPS فقط، لذلك افتح https://، واجعل Scheme في ال Reverse Proxy https.

لماذا لا يتصل Portainer بال Agent؟

ابدأ من السيرفر الأول، حيث يجب أن يطبع الأمر curl -sk -o /dev/null -w '%{http_code}' https://10.8.0.2:9001/ping الرمز 204، فإذا فشل فالمشكلة في الشبكة أو جدار الحماية Firewall، وإذا نجح الاتصال ورفض Portainer الربط فتحقق من تطابق AGENT_SECRET وتطابق الإصدارات.

الخلاصة

وصلنا لنهاية الموضوع، وأهم ما فيه:

  • Portainer CE واجهة مناسبة للفريق الصغير وللمختبرات المنزلية، أما الأدوار التفصيلية وسجلات النشاط والدعم الرسمي ففي Business Edition.
  • ثبت Portainer بملف Compose ووسم بالرقم الكامل وليس latest، حتى لا يتغير الإصدار دون علمك.
  • حساب المدير في Portainer وال Agent كلاهما يعادل صلاحية root على السيرفر، فلا تترك الواجهة ولا المنفذ 9001 على عنوان عام، واستخدم AGENT_SECRET دائماً.
  • ضع الواجهة خلف Reverse Proxy بنطاق وشهادة Let's Encrypt مع Force SSL، ثم أغلق المنفذ 9443.
  • انسخ ال Volume portainer_data وانقل النسخة إلى خارج السيرفر، وحافظ على اسمه في كل تحديث.

سجل التحديثات (Changelog)

  • سبتمبر 2026: كتابة الدليل واختباره على Portainer CE 2.45.1 LTS.
نشرة عرب رووت | ArabRoot

معرفة تستحق مكاناً في بريدك.

مقالات مختارة وأدوات مفيدة وأفكار لمشروعك القادم، في رسالة واحدة كل أسبوع.

يمكنك إلغاء الاشتراك متى شئت. الخصوصية

تم استلام طلبك. افتح بريدك واضغط رابط التأكيد لإتمام الاشتراك.