تشغيل Potato في Docker
قدّم مشروع Potato من صورة Docker المنشورة، واحفظ تعليقاته التوضيحية على قرصك، واضبط مفتاح المسؤول ومتغيرات البيئة التي تقرؤها الحاوية.
تتناول هذه الصفحة تشغيل مشروع تعليق توضيحي في Potato داخل حاوية، من أول أمر docker run إلى نقل دراسة جارية إلى إصدار جديد. الصفحة موجّهة إلى الباحثين ومديري المختبرات الذين يقدّمون دراسة من جهازهم أو من خادم يملكونه ويريدون Potato دون تثبيت Python على المضيف. ينشر Potato الصورة في GitHub Container Registry باسم ghcr.io/davidjurgens/potato، وتحتوي الصورة على الخادم واعتمادياته ولا شيء غيرهما. ولأن مجلد مشروعك يُركَّب في /app عند بدء الحاوية، تخدم صورة واحدة كل المهام.
يشغّل potato deploy الصورة نفسها على المضيفات السحابية التي يجهّزها الأمر، ويختار الوسم المطابق لإصدار Potato المثبّت لديك. تغطي صفحة تشغيل Potato محليًا أو في السحابة هذا المسار، وتغطي صفحة إعداد الإنتاج كلًا من gunicorn والوكيل العكسي وTLS على خادم تديره بنفسك.
الحصول على الصورة
يستنفد تثبيت اعتماديات Potato، وهي numpy وpandas وscipy وscikit-learn، الذاكرة عبر pip على جهاز بذاكرة 1 GB، ويستغرق من خمس إلى عشر دقائق على جهاز بذاكرة 2 GB. تصل الصورة وهذه الاعتماديات مثبّتة فيها بالفعل:
docker pull ghcr.io/davidjurgens/potato:2.14.0تأتي الصورة في نسختين، لكل منهما وسم متحرك ووسم لكل إصدار ووسم لكل إيداع:
| الوسم | المحتوى |
|---|---|
latest، 2.14.0 | اعتماديات Potato الأساسية، وعملاء النسخ الاحتياطي (huggingface_hub وboto3)، ومكتبة Authlib لتسجيل الدخول الموحّد |
latest-all، 2.14.0-all | كل ما سبق، إضافة إلى الحزمة الإضافية all التي تضم حزم SDK للذكاء الاصطناعي الخاصة بـai_support، واستيعاب ملفات PDF وDOCX، والتصدير بصيغة parquet، ومشغّل MySQL |
sha-<short>، sha-<short>-all | إيداع واحد من الفرع master |
تُبنى النسختان لمعماريتي linux/amd64 وlinux/arm64، ويعمل بناء arm64 أصليًا على Apple Silicon. لا تتضمن أي من النسختين الحزمة الإضافية vision وعجلات torch التي تبلغ عدة غيغابايت. يعمل التجزئة داخل المتصفح دون هذه الحزمة، لأن ONNX Runtime Web مضمَّن في حزمة Potato.
ثبّت وسم إصدار لأي دراسة ستستمر أكثر من يوم. يُعاد بناء الوسم latest من الفرع master مع كل تغيير، وقد يجلب أمرا docker pull بينهما أسبوع شيفرة مختلفة. أما وسم الإصدار مثل 2.14.0 فيُدفع مرة واحدة وقت الإصدار ولا يُعاد بناؤه بعد ذلك.
بناء الصورة بنفسك
ابنِ من نسخة مستنسخة من المستودع عندما تحتاج إلى حزمة إضافية لا تتضمنها أي من النسختين المنشورتين. يقبل وسيط البناء POTATO_EXTRAS أي حزمة إضافية مذكورة في setup.py الخاص بـPotato، أو عدة حزم مفصولة بفواصل:
git clone https://github.com/davidjurgens/potato
cd potato
docker build -t potato .
docker build --build-arg POTATO_EXTRAS=all -t potato:all .
docker build --build-arg POTATO_EXTRAS=all,saml -t potato:all-saml .الحزمة الإضافية saml لتسجيل الدخول عبر SAML ليست جزءًا من all. لا يثبّت Dockerfile المكتبة libxmlsec1 التي تُترجَم الحزمة الإضافية مقابلها إلا عندما يذكر POTATO_EXTRAS الحزمة saml. شغّل البناء المحلي بوسمه، مثل potato:all، في كل موضع تذكر فيه هذه الصفحة ghcr.io/davidjurgens/potato:2.14.0.
تشغيل مشروع
يحتوي مجلد المشروع على config.yaml وكل ملف يذكره الإعداد. تستخدم أمثلة هذه الصفحة مهمة مشاعر من ثلاثة عناصر بالبنية التالية:
myproject/
├── config.yaml
└── data/
└── items.jsonlيُبقي الإعداد كل مسار نسبيًا إلى مجلد المشروع:
annotation_task_name: "Sentiment pilot"
task_dir: .
data_files:
- data/items.jsonl
item_properties:
id_key: id
text_key: text
output_annotation_dir: annotation_output/
user_config:
allow_all_users: true
annotation_schemes:
- annotation_type: radio
name: sentiment
description: "What is the sentiment of this sentence?"
labels: [positive, neutral, negative]يمثّل كل سطر في data/items.jsonl عنصرًا واحدًا:
{"id": "1", "text": "The battery lasts all day."}
{"id": "2", "text": "The screen cracked within a week."}
{"id": "3", "text": "It arrived on Tuesday."}شغّل الخادم من المجلد الذي يحتوي على myproject:
docker run -d --name potato -p 8000:7860 \
-v "$PWD/myproject:/app" \
ghcr.io/davidjurgens/potato:2.14.0تصبح المهمة بعد ذلك على http://localhost:8000. يربط الوسيط -p 8000:7860 المنفذ 8000 على جهازك بالمنفذ 7860 الذي يستمع إليه الخادم داخل الحاوية. ويركّب الوسيط -v مجلد المشروع في /app. يجب أن يكون الجانب الأيسر مسارًا مثل $PWD/myproject، لأن Docker يقرأ اسمًا مجردًا مثل myproject على أنه اسم وحدة تخزين جديدة فارغة. يتتبع docker logs -f potato سجل الخادم، ويوقف docker stop potato الخادم.
يختار المشروع الذي فيه عدة ملفات إعداد واحدًا منها بالمتغير POTATO_CONFIG، وهو مسار نسبي إلى /app:
docker run -d --name potato -p 8000:7860 \
-v "$PWD/myproject:/app" \
-e POTATO_CONFIG=configs/pilot.yaml \
ghcr.io/davidjurgens/potato:2.14.0تشغيل دراسة تمتد أسابيع
تحتاج الدراسة التي تمتد أسابيع إلى مفتاح توقيع للجلسات يبقى ثابتًا عبر عمليات إعادة التشغيل والتحديث. من دون POTATO_SECRET_KEY، يختار كل بدء للخادم مفتاحًا عشوائيًا جديدًا ويُخرج كل معلّق من حسابه. أنشئ ملف بيئة مرة واحدة خارج مجلد المشروع، ومرّر الملف نفسه إلى كل أمر docker run:
printf 'POTATO_SECRET_KEY=%s\nPOTATO_ADMIN_API_KEY=%s\n' \
"$(openssl rand -hex 32)" "$(openssl rand -hex 32)" > potato.env
chmod 600 potato.env
docker run -d --name potato -p 8000:7860 \
-v "$PWD/myproject:/app" \
--env-file potato.env \
--restart unless-stopped \
ghcr.io/davidjurgens/potato:2.14.0يشرح قسم مفتاح المسؤول السطر الثاني من الملف. ويعيد --restart unless-stopped الحاوية إلى العمل بعد عطل أو بعد إعادة تشغيل المضيف.
أوامر أخرى في الصورة
يحل أي شيء يأتي بعد اسم الصورة محل الخادم. افحص إعدادًا بأداة التحقق التي تشحنها الصورة، أو افتح صدفة داخل الحاوية:
docker run --rm -v "$PWD/myproject:/app" \
ghcr.io/davidjurgens/potato:2.14.0 potato validate config.yaml --strict
docker run --rm -it -v "$PWD/myproject:/app" \
ghcr.io/davidjurgens/potato:2.14.0 shملكية الملفات على Linux
يعمل الخادم في الصورة بالمعرّف uid 1000، ويحتفظ التركيب bind mount بالملكية التي للمجلد على المضيف. على Linux، المجلد الذي أنشأته أنت مملوك لمعرّفك uid، والمجلد الذي أنشأه root مملوك لـroot. ما لم يكن مالك المجلد هو uid 1000، لا يستطيع الخادم كتابة التعليقات التوضيحية في المجلد. تفحص الحاوية المجلد قبل بدء الخادم وتتوقف برسالة ERROR: /app is not writable by uid 1000 بدلًا من أن تفشل في منتصف بدء التشغيل. يحل أي من الأمرين أدناه المشكلة:
sudo chown -R 1000:1000 myproject # hand the folder to the container user
docker run --user "$(id -u):$(id -g)" ... # or run the container as yourselfمع --user، تصبح التعليقات التوضيحية وملف مفتاح المسؤول الذي يكتبه Potato مملوكة لحسابك أنت أيضًا. يتجاهل Docker Desktop على macOS وWindows الملكية في التركيبات bind mount، وقد يفشل مشروع يعمل على Mac على خادم Linux. يتخطى POTATO_ALLOW_READONLY_APP=1 هذا الفحص. ما زال Potato يكتب التعليقات التوضيحية وpotato.log وقواعد بيانات SQLite داخل المشروع، لذلك اضبط المتغير فقط عندما تكون هذه المسارات قابلة للكتابة عبر تركيبات منفصلة.
تبدأ بعض المضيفات كل حاوية بصفة root أيًا كان ما تحدده الصورة. وعندما تبدأ الحاوية بصفة root، تمنح الحاوية المجلد /app للمستخدم potato في الصورة وتبدأ الخادم بصفته. اضبط POTATO_RUN_AS_ROOT=1 لإبقاء root بدلًا من ذلك.
حفظ التعليقات التوضيحية
يكتب Potato كل ما تجمعه الدراسة في مجلد المشروع. تذهب التعليقات التوضيحية تحت output_annotation_dir، في دليل لكل معلّق يضم الملف user_state.json الخاص به. وتوجد قاعدتا بيانات SQLite بجوار config.yaml. تحتفظ project.sqlite بالمذكرات ودليل الترميز والحالات وفهرس البحث وسير عمل المراجعة، وتحتفظ datasets.sqlite بمجموعات بيانات التقييم وإصداراتها. لا يمكن إعادة بناء أي من القاعدتين من ملفات البيانات. ومع التركيب bind mount، تكون هذه الملفات كلها على قرصك وتبقى هناك عند إزالة الحاوية.
يجب أن يُحَلّ output_annotation_dir داخل مجلد المشروع. يوقف مسار مثل /data/annotations الخادم عند بدء التشغيل برسالة output_annotation_dir: Path '/data/annotations' resolves to '/data/annotations' which is outside the project directory '/app'. احتفظ بمسار نسبي مثل annotation_output/. لا يقع مجلد /data في الصورة داخل المشروع أيضًا، ولا يكتب Potato فيه شيئًا.
انسخ قاعدة بيانات من حاوية قيد التشغيل بأمر النسخ الاحتياطي في SQLite، لا كملف عادي. تعمل project.sqlite في وضع WAL بينما يكتب الخادم في قاعدة البيانات، وقد تكون النسخة العادية تالفة أو تفتقر إلى عمل حديث دون أي تحذير. تتضمن الصورة الأداة sqlite3 لأخذ اللقطة:
docker exec potato sqlite3 /app/project.sqlite ".backup /tmp/snap.sqlite"
docker cp potato:/tmp/snap.sqlite ./project.sqliteتمسح معظم مضيفات الحاويات المُدارة نظام ملفات الحاوية عند إعادة تشغيلها. على مضيف كهذا، أبقِ المشروع على تخزين دائم مركَّب في /app، أو أضف كتلة backup إلى الإعداد. تنسخ الكتلة التعليقات التوضيحية ولقطات قواعد البيانات إلى حاوية S3 أو إلى مجموعة بيانات على Hugging Face وفق جدول زمني، وتستعيدها عندما يبدأ الخادم بقرص فارغ. تتضمن كل نسخة من الصورة العملاء التي تحتاج إليها الكتلة.
متغيرات البيئة
تقرأ الحاوية هذه المتغيرات عند بدء التشغيل:
| المتغير | القيمة الافتراضية | الغرض |
|---|---|---|
POTATO_CONFIG | config.yaml | مسار الإعداد داخل الحاوية، نسبيًا إلى /app |
PORT | 7860 | المنفذ الذي يستمع إليه الخادم داخل الحاوية |
GUNICORN_WORKERS | 1 | عمليات العمال؛ أي قيمة أخرى توقف الحاوية عند بدء التشغيل |
GUNICORN_THREADS | 8 | الخيوط في العامل الواحد، وهي عدد الطلبات التي تُخدَّم في آن واحد |
GUNICORN_TIMEOUT | 120 | الثواني التي يجوز فيها أن يبقى العامل صامتًا قبل أن يعيد gunicorn تشغيله |
POTATO_SECRET_KEY | عشوائي عند كل بدء | يوقّع ملفات تعريف ارتباط الجلسة؛ يتقدم عليه secret_key في الإعداد |
POTATO_ADMIN_API_KEY | ملف مولَّد | مفتاح واجهة المسؤول البرمجية؛ يتقدم عليه admin_api_key في الإعداد |
POTATO_GENERATED_TEMPLATES_DIR | يُختار عند بدء التشغيل | المكان الذي يكتب فيه Potato قوالب المهمة التي يبنيها عند بدء التشغيل |
POTATO_BUNDLE_URL | غير مضبوط | عنوان URL لملف .tar.gz للمشروع يُنزَّل إلى /app عند بدء التشغيل |
POTATO_BUNDLE_SHA256 | غير مضبوط | المجموع الاختباري الذي يجب أن يطابقه المشروع المنزَّل |
POTATO_BUNDLE_TOKEN | غير مضبوط | يُرسل بصيغة Authorization: Bearer مع التنزيل |
POTATO_RUN_AS_ROOT | غير مضبوط | القيمة 1 تُبقي الخادم يعمل بصفة root عندما تبدأ الحاوية بصفة root |
POTATO_ALLOW_MULTIWORKER | غير مضبوط | القيمة 1 تسمح بأن يتجاوز GUNICORN_WORKERS العدد 1، وهذا يُفقد التعليقات التوضيحية في دراسة حقيقية |
POTATO_ALLOW_READONLY_APP | غير مضبوط | القيمة 1 تتخطى فحص بدء التشغيل الذي يتأكد أن /app قابل للكتابة |
تحتاج الحاوية التي تغيّر PORT إلى المنفذ نفسه على يمين -p، كما في -p 8000:9000 للقيمة PORT=9000.
عدد العمال والخيوط
ترفض الحاوية البدء بأكثر من عامل gunicorn واحد. يحتفظ Potato بمجموعة العناصر وطابور الإسناد وحالة كل معلّق في ذاكرة عملية واحدة. وسيحتفظ عامل ثانٍ بنسخته الخاصة من الثلاثة ويسند عناصر أسندها العامل الأول بالفعل. يعيد كل حفظ كتابة user_state.json كاملًا، وسيتخلص العامل الذي يحفظ أخيرًا من تعليقات العامل الآخر دون أي خطأ. ارفع GUNICORN_THREADS للحصول على مزيد من الطلبات المتزامنة بدلًا من ذلك، لأن الخيوط تتشارك نسخة واحدة من الحالة.
القوالب المولَّدة
يبني Potato قالبًا لصفحة التعليق التوضيحي في كل مهمة عند بدء التشغيل. خارج الحاوية، يذهب القالب إلى الحزمة المثبّتة متى كان دليل الحزمة قابلًا للكتابة. تثبّت الصورة Potato بصفة root وتشغّل الخادم بالمعرّف uid 1000، ولذلك لا يستطيع الخادم الكتابة في دليل الحزمة. يكتب Potato القوالب بدلًا من ذلك في دليل تحت /tmp لا يقرؤه ولا يكتب فيه سوى مستخدم الخادم، ويسمّي سجل بدء التشغيل هذا الدليل. يعيد Potato بناء القوالب من الإعداد عند كل بدء، ولا يكلّف فقدان الدليل شيئًا. اضبط POTATO_GENERATED_TEMPLATES_DIR لوضع القوالب في مكان آخر، مثل تركيب tmpfs.
تنزيل المشروع عند بدء التشغيل
المضيفات التي تشغّل صورة فقط، مثل Render وFly وRailway وECS، ليس لديها مجلد تركّبه. عند ضبط POTATO_BUNDLE_URL، تنزّل الحاوية ملف .tar.gz للمشروع، وتقارن التنزيل بالقيمة POTATO_BUNDLE_SHA256، وتفك المشروع في /app قبل أن يبدأ الخادم. تكتب الحاوية المجموع الاختباري في /app/.potato-bundle-sha، وتتخطى إعادة التشغيل على قرص دائم تنزيلًا يطابق مجموعه الاختباري. وفي الحزمة التي يبنيها potato deploy، لا يحل إصدار جديد من المشروع أبدًا محل مخرجات التعليقات ولا قواعد بيانات SQLite الموجودة على القرص. يضبط potato deploy up هذه المتغيرات نيابة عنك.
مفتاح المسؤول في الحاوية
تأخذ لوحة المسؤول على /admin وواجهة المسؤول البرمجية مفتاحًا مشتركًا واحدًا، يُرسل في الترويسة X-API-Key أو يُكتب في صفحة تسجيل دخول المسؤول. يقرأ Potato المفتاح من مفتاح الإعداد admin_api_key في المستوى الأعلى أولًا، ثم من متغير البيئة POTATO_ADMIN_API_KEY. في الحاوية، يُبقي متغير البيئة المفتاح خارج config.yaml وخارج أي مستودع يضم المشروع. يضبط الملف potato.env في قسم الدراسات الطويلة هذا المتغير، ويصبح مفتاح المسؤول هو ما يحتويه ذلك الملف:
grep POTATO_ADMIN_API_KEY potato.envعندما لا يضبط الإعداد ولا البيئة مفتاحًا، يولّد Potato مفتاحًا في أول مرة يفتح فيها أحدٌ /admin أو يستدعي نقطة نهاية للمسؤول. يكتب Potato المفتاح المولَّد في admin_api_key.txt داخل دليل المهمة. في الحاوية، دليل المهمة هو /app، أي مجلد المشروع المركَّب. الملف مقروء لمستخدم الخادم وحده، ويقرأ Potato الملف نفسه بعد إعادة التشغيل. يسمّي سجل الخادم الملف ولا يطبع المفتاح أبدًا. اقرأ المفتاح عبر الحاوية:
docker exec potato cat /app/admin_api_key.txtعلى مضيف Linux سلّمتَ فيه مجلد المشروع إلى uid 1000، لا يستطيع حسابك قراءة admin_api_key.txt دون sudo. أما الحاوية التي بدأت بالخيار --user "$(id -u):$(id -g)" فتكتب الملف بصفة حسابك أنت. راجع صفحة لوحة الإدارة لمعرفة ما يفتحه المفتاح.
وضع التصحيح في الحاوية
أبقِ debug: false في أي حاوية تخدم دراسة. مع debug: true في الإعداد، يغيّر Potato سلوك ميزتين:
- صفحات المسؤول بلا مفتاح. تتخطى لوحة المسؤول وواجهته البرمجية المفتاح لطلب يأتي من عنوان loopback ولا يحمل الترويسة
X-Forwarded-ForولاX-Real-IPولاForwarded. على شبكة الجسر الافتراضية في Docker، يصل الطلب إلى المنفذ المنشور إلى الحاوية من عنوان الجسر ويظل يحتاج إلى المفتاح. ومع--network host، يكون الطلب القادم من جهاز المضيف طلب loopback ولا يحتاج إلى مفتاح. والوكيل العكسي الموجود في فضاء أسماء الشبكة نفسه والذي لا يضيف ترويسة إعادة توجيه يجعل كل طلب يمرره الوكيل يبدو محليًا. - حساب تصحيح مشترك. مع ضبط
debug_phaseأيضًا، يُسجَّل كل زائر دخوله بحساب مشترك واحد هوdebug_userويُنقل إلى تلك المرحلة. الحساب ليس مسؤولًا، لكن كل زائر يتشارك إجابات الحساب.
يسجّل الخادم تحذيرًا عند بدء التشغيل كلما كان debug مفعّلًا. والأمر المشغَّل داخل الحاوية بـdocker exec طلب loopback. ولذلك يعيد docker exec potato curl -s http://127.0.0.1:7860/admin/health في وضع التصحيح تقرير صحة المسؤول دون مفتاح.
فحوصات الصحة
لا يحتاج GET /health إلى مصادقة، ولا يبلّغ إلا عما إذا كان الخادم يعمل. تعيد النقطة {"status": "ok"} متى صار الخادم جاهزًا، والحالة 503 ما دام الخادم يحمّل البيانات، ويستطيع موازن الحمل أو المنسّق أن يستطلع هذه النقطة بوصفها فحص الجاهزية. يستطلع HEALTHCHECK الخاص بالصورة النقطة /health كل 30 ثانية ويمنح مهلة بدء مدتها 90 ثانية للمهام الكبيرة، ويعرض docker ps النتيجة. ويبلّغ GET /admin/health عن اسم المهمة وحالة مديري العناصر والمعلّقين، وتحتاج النقطة إلى مفتاح المسؤول في الترويسة X-API-Key.
Docker Compose
لا يشحن مستودع Potato ملف Compose. تعرض صفحة إعداد الإنتاج ملف Compose يشغّل هذه الصورة خلف nginx، مع تركيب مجلد المشروع في /app وقراءة مفتاحي الجلسة والمسؤول من البيئة.
التحديث إلى إصدار جديد
يستبدل تحديث Potato الحاوية ويترك مجلد المشروع، بكل تعليق توضيحي وقاعدة بيانات، في مكانه. قبل التبديل، اسحب الإصدار الجديد، وافحص الإعداد بأداة التحقق في الإصدار الجديد، وخذ لقطة من قاعدة بيانات المشروع. استبدل 2.14.0 بالإصدار الذي تنتقل إليه:
docker pull ghcr.io/davidjurgens/potato:2.14.0
docker run --rm -v "$PWD/myproject:/app" \
ghcr.io/davidjurgens/potato:2.14.0 potato validate config.yaml --strict
docker exec potato sqlite3 /app/project.sqlite ".backup /tmp/snap.sqlite"
docker cp potato:/tmp/snap.sqlite ./project-before-update.sqliteثم استبدل الحاوية الجارية بحاوية على الوسم الجديد، مستخدمًا التركيب نفسه وملف البيئة نفسه:
docker stop potato
docker rm potato
docker run -d --name potato -p 8000:7860 \
-v "$PWD/myproject:/app" \
--env-file potato.env \
--restart unless-stopped \
ghcr.io/davidjurgens/potato:2.14.0ولأن potato.env يُبقي POTATO_SECRET_KEY كما هو، يظل المعلّقون مسجّلين دخولهم عبر التبديل، ولا يتغير مفتاح المسؤول.
استكشاف الأخطاء وإصلاحها
ERROR: config file not found: config.yaml. لم يُركَّب المشروع حيث بحث الخادم. يسرد الخطأ محتويات /app للمقارنة مع الوسيط -v لديك. القائمة الفارغة تعني عادةً اسمًا مجردًا مثل -v myproject:/app. يقرأ Docker الاسم المجرد على أنه وحدة تخزين جديدة فارغة لا مجلدك.
ERROR: /app is not writable by uid 1000. لا يستطيع الخادم الكتابة في مجلد المشروع. سلّم المجلد إلى uid 1000 أو شغّل الحاوية بالخيار --user. يعطي قسم ملكية الملفات على Linux الأمرين.
output_annotation_dir ... is outside the project directory '/app'. يشير الإعداد بمخرجات التعليقات إلى خارج المجلد المركَّب. استخدم مسارًا نسبيًا مثل annotation_output/.
يُخرَج الجميع من حساباتهم بعد إعادة التشغيل. لم يُضبط مفتاح توقيع، فاختار الخادم مفتاحًا عشوائيًا جديدًا عند البدء. اضبط POTATO_SECRET_KEY في ملف بيئة ومرّر الملف إلى كل أمر docker run.
تخرج الحاوية بخطأ يذكر GUNICORN_WORKERS. عدد العمال أكبر من 1. اضبط GUNICORN_WORKERS=1، أو احذف المتغير، وارفع GUNICORN_THREADS بدلًا من ذلك.
ترفض صفحة تسجيل دخول المسؤول كل مفتاح. يتقدم admin_api_key في الإعداد على POTATO_ADMIN_API_KEY، ويتقدم كلاهما على admin_api_key.txt. افحص الإعداد أولًا، ثم docker exec potato printenv POTATO_ADMIN_API_KEY.
قراءات إضافية
- تشغيل Potato محليًا أو في السحابة - أهداف
potato deployالتي تشغّل هذه الصورة نيابة عنك - إعداد الإنتاج - gunicorn وnginx وTLS والجلسات والنسخ الاحتياطية على خادمك الخاص
- الوكيل العكسي - تقديم Potato تحت بادئة مسار URL
- لوحة الإدارة - ما يفتحه مفتاح المسؤول
لتفاصيل التنفيذ، راجع الوثائق المصدرية.