لنفرض أن لديك سيرفراً تعمل عليه عدة خدمات، وأردت أن تعرف ما الذي يعمل عليه الآن، أو أن تقرأ سجل 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 حرفاً على الأقل، ثم الصق رمز الإعداد:

docker compose restart portainer) ثم تستخرج رمز الإعداد الجديد من السجل وتكمل الخطوة فوراً، ولاحظ أن الرمز يتغير مع كل إعادة تشغيل، لذلك استخدم آخر سطر setup_token في السجل.قد تظهر بعد ذلك صفحة عن Edge Compute، فتخطها بالزر Skip إذا لم تكن تدير أجهزة خلف NAT، ثم يظهر معالج Wizard البيئات وقد اكتشف Portainer المحرك المحلي Local Engine عبر ال socket:

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

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

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
- /:/hostcd /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:

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

agent على شبكة Docker، أما على سيرفراتك فسوف يظهر عنوان IP/:/host، وهذا السطر لا يلزم إلا لميزات إدارة المضيف Host Management، فاحذفه إذا لم تحتج إليها. لذلك لا تنشر المنفذ 9001 على عنوان عام Public IP، وتذكر أن ufw لا يحجب منفذاً نشره Docker، وإنما انشره على عنوان الشبكة الخاصة كما في المثال، واستخدم AGENT_SECRET دائماً. وإذا لم تتوفر شبكة خاصة بين السيرفرين فاستخدم Edge Agent، والسبب أنه هو من يبادر بالاتصال بـ Portainer ولا يحتاج إلى منفذ وارد Inbound Port، وهو ما توصي به وثائق Portainer في أغلب الحالات.الوصول عبر نطاق وشهادة TLS
المنفذ 9443 بشهادته الموقعة ذاتياً يصلح للدقائق الأولى فقط، أما في بيئة الإنتاج فضع Portainer خلف Reverse Proxy بنطاق مثل portainer.example.com وشهادة Let's Encrypt. وإذا كان Nginx Proxy Manager على نفس السيرفر، فأسهل طريقة أن تضع ال Containers الاثنين على شبكة Docker مشتركة، وبهذا الشكل لا تحتاج إلى نشر أي منفذ لـ Portainer:
docker network create proxyservices:
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 Names | portainer.example.com |
| Scheme | https |
| Forward Hostname / IP | portainer |
| Forward Port | 9443 |
| 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 إلى إصدار أحدث
- راجع صفحة الإصدارات، وابق على قناة LTS في بيئة الإنتاج.
- أنشئ نسخة احتياطية كما في القسم السابق.
- غير الوسم في
compose.yamlوفي ملف ال Agent على كل سيرفر، والسبب أن إصدار ال Agents يجب أن يطابق إصدار Portainer دائماً. - اسحب ال 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.