العودة إلى المدونة

كيفية تأمين وتوسيع نطاق تطبيق Django باستخدام Docker و Nginx و Let’s Encrypt

كيفية تأمين وتوسيع نطاق تطبيق Django باستخدام Docker و Nginx و Let’s Encrypt

يدخل ملايين المستخدمين إلى الإنترنت للوصول إلى المعلومات لأغراض مختلفة بما في ذلك التعلم والترفيه والأخبار ومشاركة تقدم حياتهم’ مع الأصدقاء. وبالتالي، عند نشر تطبيق ما، فمن مصلحتك القصوى تنفيذ بنية تحتية آمنة للغاية وقابلة للتطوير لتطبيقك. توفر السحابة طرقًا مختلفة لتأمين وتوسيع نطاق Django . يعد التوسيع الأفقي أحد الأساليب التي يمكن أن تسمح لك بتشغيل نسخ متعددة من تطبيقك. يضمن ذلك أن يكون التطبيق أكثر مقاومة للأخطاء ومتاحًا بشكل كبير. كما أنه يزيد من أدائه لمعالجة طلبات متعددة في وقت واحد.

توسيع تطبيق Django أفقيًا

يمكنك توسيع تطبيق Django أفقيًا عن طريق توفير العديد من خوادم التطبيقات التي تقوم بتشغيل تطبيق Django وخادم WSGI HTTP الخاص به (مثل Gunicorn أو uWSGI). ستحتاج بعد ذلك إلى إعداد بنية تحتية لتوزيع الطلبات الواردة عبر خوادم التطبيقات هذه. موازن التحميل و وكيل عكسي مثل Nginx مساعدة بنيتك التحتية في توزيع حركة المرور. يمكن لـ Nginx نشر شهادات SSL مما يضمن اتصالات آمنة بتطبيقك عبر HTTPS. أخيرًا، يمكن لـ Nginx أيضًا توفير التخزين المؤقت للمحتوى الثابت لتقليل الحمل على خادمك.

قد يكون تكوين هذه المكونات المختلفة بشكل منفصل وضمان تواصلها مهمة شاقة. لحسن الحظ، فإن استخدام Docker يسهل عملية التكوين ويضمن أن تتصرف المكونات المختلفة بنفس الطريقة بغض النظر عن مكان نشرها.

ما ستفعله في هذا الدليل

في هذا الدليل، ستتعلم كيفية توسيع تطبيق Django المعبأ في حاويات أفقيًا، والمقدم بواسطة خادم Gunicorn WSGI HTTP. ستقوم بتوفير خادمي تطبيقات، يحتوي كل منهما على Docker مثبتًا، ويقومان بتشغيل نفس النسخة من حاوية تطبيق Django و Gunicorn.

ستقوم أيضًا بتأمين تطبيقك باستخدام Let’s Encrypt شهادة SSL عن طريق توفير وتكوين خادم وكيل ثالث سيقوم بتشغيل حاوية وكيل عكسي Nginx وحاوية عميل Certbot. Certbot هي حزمة تساعد في إدارة شهادات SSL من جهة إصدار الشهادات Let’s Encrypt. حيث تقوم باسترداد الشهادة، وتكوين كتل خادم Nginx بموقع الشهادة، وإدارة التجديدات التلقائية. وتقوم بذلك عن طريق تكوين وظيفة cron للتحقق بشكل دوري مما إذا كانت الشهادة على وشك الانتهاء وتحتاج إلى تجديد. من خلال الحفاظ على تحديث شهادة SSL الخاصة بك، سيحصل موقع الويب الخاص بك دائمًا على تصنيف أمان عالٍ على SSL Labs.

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

هذا البرنامج التعليمي هو الثاني في سلسلة من ثلاثة برامج تعليمية تعمل مع Django و Docker و Kubernetes. يجب عليك أولاً اتباع الخطوات الموضحة في البرنامج التعليمي حول Building a Django and Gunicorn Application with Docker on Ubuntu. في هذا البرنامج التعليمي، قمنا بإعداد كود المشروع الأساسي، وملف Dockerfile، وتوصيل التطبيق بـ MinIo خدمة التخزين البسيط (S3) لتقديم ملفاتنا الثابتة.

المتطلبات الأساسية

لمتابعة هذا البرنامج التعليمي، ستحتاج إلى ما يلي:

  1. أربعة خوادم Ubuntu 20.04:

إذا كنت قد اتبعت الخطوات في البرنامج التعليمي للمتطلبات الأساسية، Building a Django and Gunicorn Application with Docker on Ubuntu، فلديك بالفعل خادمان من الخوادم الأربعة:

  • سيقوم الخادم الأول بتشغيل مثيل قاعدة بيانات PostgreSQL. اتبع الخطوتين 1 و 2 من البرنامج التعليمي: Building a Django and Gunicorn Application with Docker on Ubuntu لإعداد قاعدة البيانات. يجب تعديل تكوينات Postgres للسماح بالاتصالات الخارجية من عناوين IP الخاصة بخادم التطبيق فقط.

  • سيستضيف الخادمان الثاني و الثالث الحاويات الخاصة بكود تطبيقك. يجب أن يكون لديك بالفعل الخادم الثاني قيد التشغيل من البرنامج التعليمي للمتطلبات الأساسية. سنقوم بتعديل جدار الحماية الخاص به للسماح فقط بالاتصالات الخارجية من عنوان IP الخاص بالخادم الوكيل. يمكنك اتباع الخطوات من 1 إلى 4 من هذا البرنامج التعليمي خطوة بخطوة لمساعدتك في إعداد خادم Ubuntu الخاص بك على CloudSigma.

  • الـ رابع سيكون خادم الـ الوكيل الذي يتعامل مع موازنة التحميل وتوزيع حركة المرور إلى حاويتي خادم التطبيق.

  1. يجب تثبيت Docker على خادمي التطبيق وخادم الوكيل.

    بعد اتباع الخطوات الواردة في البرنامج التعليمي للمتطلبات الأساسية، يجب أن يكون Docker مثبتًا بالفعل على أحد الخوادم. يمكنك اتباع الخطوات 1 و 2 و 3 من البرنامج التعليمي الخاص بنا حول تثبيت وتشغيل Docker. تذكر إضافة مستخدم sudo الذي تم إنشاؤه أعلاه إلى مجموعة Docker.

  2. احصل على اسم نطاق مسجل وقم بإعداد سجلات DNS الخاصة به لتشير إلى عنوان IP العام لخادم الوكيل. لأغراض التوضيح، سنستخدم example_domain.com.
  1. إعداد خدمة تخزين الكائنات S3. لقد استخدمنا MinIO كخدمة تخزين في البرنامج التعليمي للمتطلبات الأساسية. لذلك، اتبع الشروحات في الخطوة 5 من البرنامج التعليمي للمتطلبات الأساسية لإعداد مساحة تخزين MinIO الخاصة بك.

الخطوة 1: التحقق من أن خادم تطبيق Django الأول يعمل

كما هو موضح في المتطلبات الأساسية، يأتي هذا الدليل بعد البرنامج التعليمي حول بناء تطبيق Django و Gunicorn باستخدام Docker على Ubuntu. إذا كنت قادمًا من هذا البرنامج التعليمي وقمت بالفعل بتنفيذ الخطوات، فيجب أن يكون الخادم الأول قيد التشغيل لديك. تعتمد شيفرة التطبيق على وثائق Django لـ البرنامج التعليمي لتطبيق الاستطلاعات (Polls). من المهم أن تقرأ هذه الخطوات لتكوين فهم للإعداد الأولي. إذا قمت بتنفيذ الخطوات الواردة في البرنامج التعليمي، يمكنك تخطي هذه الخطوة الأولى.

بخلاف ذلك، يمكنك فقط استنساخ الفرع المهيأ لـ Docker (Dockerized) في خادمك. ابدأ بتسجيل الدخول إلى خادم التطبيق الأول الخاص بك ونفذ أمر git التالي لاستنساخ فرع django-polls-docker من مستودع django-polls repository:

بعد ذلك، انتقل إلى دليل django-polls :

cd django-polls

في هذا الدليل، ستجد ملف Dockerfile الذي يستخدمه Docker لبناء صورة التطبيق، ودليل django-polls الذي يحتوي على شيفرة تطبيق Python، وملف env يحتوي على قائمة بمتغيرات البيئة التي سيتم تمريرها إلى الحاوية عند بدء التشغيل لتعديل سلوكها. في ملف Dockerfile، نحدد تبعيات حزمة Django من خلال ملف requirements.txt. بالإضافة إلى ذلك، نحتاج إلى الإعلان عن منفذ 8000 ليتم استخدامه لقبول حركة المرور الواردة، وتعيينه لتشغيل خادم gunicorn مع 3 عمال (workers). لمعرفة المزيد حول تعليمات Dockerfile، يرجى إلقاء نظرة على الخطوة 7 من البرنامج التعليمي بناء تطبيق Django و Gunicorn باستخدام Docker على Ubuntu.

يمكنك بناء صورة Docker باستخدام الأمر:

docker build -t django-polls:v1 .

بعد أن يقوم Docker ببناء الصورة، يمكنك سرد الصور المتاحة على الخادم باستخدام الأمر التالي:

docker images

إليك المخرجات عندما قمنا بتشغيل الأمر:

Django Application scrn 1

بعد ذلك، نحتاج إلى تعديل ملف env المستخدم في تكوين بيئة التشغيل. يتم تمرير هذا الملف إلى حاوية تشغيل Docker عند تشغيل الحاوية. افتح ملف env باستخدام محرر nano:

إنّ env ملف يحتوي على بعض النصوص المؤقتة التي تحتاج إلى تعديلها وملئها بقيمك الصحيحة:

  • DJANGO_SECRET_KEY: قم بتوليد قيمة فريدة وغير متوقعة كما هو موضح في وثائق Django. يمكنك استخدام هذا الأمر لتوليد سلسلة نصية عشوائية وتعيينها للمتغير:  python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'.

  • DJANGO_ALLOWED_HOSTS: تُستخدم هذه القيمة لتأمين تطبيقك من هجمات HTTP Host Header. يمكنك تعيينها إلى *، وهي علامة مطابقة عامة تطابق جميع المضيفين إذا كنت في وضع التطوير. عند نشر تطبيقك في بيئة الإنتاج، قم بتعيين هذا إلى اسم النطاق المسجل الخاص بك. بالنسبة للعرض التوضيحي الخاص بنا، فهو example_domain.com.

  • DB_DATABASE: قم بتعيين هذا إلى اسم قاعدة بيانات PostgreSQL التي أنشأتها في قسم المتطلبات الأساسية ، وبالنسبة لحالتنا فهو polls_db.

  • DB_USERNAME: قم بتعيين هذا إلى اسم المستخدم الذي اخترته لقاعدة بياناتك.

  • DB_PASSWORD: قم بتعيين هذا إلى كلمة المرور التي اخترتها لقاعدة بياناتك.

  • DB_HOST: قم بتعيين هذا إلى المضيف الذي يقوم بتشغيل مثيل قاعدة البيانات الخاصة بك كما قمت بإعداده في قسم المتطلبات الأساسية . تم شرح ذلك في الخطوتين 1 و 2 من البرنامج التعليمي بناء تطبيق Django و Gunicorn باستخدام Docker على Ubuntu لإعداد قاعدة البيانات.

  • DB_PORT: قم بتعيين هذا إلى منفذ قاعدة بياناتك.

احفظ الملف وأغلقه بمجرد الانتهاء من التعديل. مع وجود بيانات اعتماد قاعدة البيانات الخاصة بنا في مكانها الصحيح، يمكننا إنشاء مخطط قاعدة البيانات عن طريق تشغيل الحاوية وتجاوز أمر CMD المحدد في Dockerfile. يمكنك العثور على مزيد من المعلومات حول نقطة دخول Dockerfile من الوثائق الرسمية. بعد ذلك، قم بتنفيذ الأمر التالي:

في هذا الأمر، نقوم بتشغيل صورة django-polls:v1 وتمرير ملف env الذي تم تعديله سابقًا. الجزء: sh -c "python manage.py makemigrations && python manage.py migrate يقوم بإنشاء مخطط قاعدة البيانات المحدد بواسطة كود التطبيق. إذا كنت تقوم بتنفيذ الأمر للمرة الأولى، فيجب أن ترى مخرجًا مشابهًا يشير إلى إنشاء مخطط قاعدة البيانات:

Django Application scrn 2

بمجرد إنشاء المخطط، يمكننا إنشاء مستخدم Django الخارق. نفذ الأمر التالي لبدء تشغيل الحاوية باستخدام واجهة تفاعلية (interactive shell):

يبدأ الأمر تشغيل الحاوية مع موجه أوامر (shell prompt) يمكنك استخدامه للتفاعل مع واجهة Python. لنقم بإنشاء مستخدم باستخدام الأمر التالي:

اتبع المطالبات لتقديم اسم مستخدم، وعنوان بريد إلكتروني، وكلمة مرور. أعد كتابة كلمة المرور، واضغط على Enter لإنشاء المستخدم. اخرج من الواجهة وأوقف الحاوية بالضغط على CTRL+D.

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

يقوم الأمر بتوليد ورفع الملف إلى خدمة تخزين الكائنات التي قمت بتكوينها. إليك المخرج:

object storage

يمكنك الآن تشغيل التطبيق دون تحديد أي أمر إضافي لتجاوز أمر CMD الافتراضي المحدد في Dockerfile:

Django Application scrn 3

يقوم Docker بتشغيل الأمر الافتراضي المحدد في Dockerfile، ويبدأ تشغيل الحاوية باستخدام خادم gunicorn ، ويعرض منفذ الحاوية 8000 ، ويقوم بربطه بمنفذ Ubuntu 80 . يمكنك الآن عرض واجهة التطبيق في متصفحك عن طريق الوصول إلى عنوان IP الخاص بالخادم الأول في شريط العنوان لديك: http://FIRST_SERVER_IP.

ستحصل على 404 Page Not Found لأننا لم نحدد أي شيء لـ / المسار. انتقل إلى http://FIRST_SERVER_IP/polls لرؤية واجهة Polls:

Django Application image 1

قم بزيارة واجهة المسؤول لإنشاء بعض الاستطلاعات: http://FIRST_SERVER_IP/admin:

polls

أدخل بيانات الاعتماد التي قمت بتعيينها باستخدام الأمر createsuperuser أعلاه للوصول إلى واجهة الإدارة:

polls administration

إذا قمت بعرض مصدر الصفحة، فستلاحظ أنه يتم جلب الملفات الثابتة من حاوية التخزين كما هو محدد. بعد التأكد من أن الحاوية تخدم التطبيق كما هو متوقع، يمكنك إيقاف الحاوية عن طريق الضغط على CTRL+C في الطرفية.

بعد ذلك، نحتاج إلى إبقاء الحاوية قيد التشغيل في وضع detached، حتى نتمكن من الخروج من جلسة SSH للخادم الأول. سيؤدي هذا إلى ترك الحاوية تعمل في الخلفية. نفذ الأمر التالي:

تقوم العلامة -d بتشغيل الحاوية في وضع detached حتى تتمكن من الاستمرار في العمل في الخلفية. وتقوم العلامة --rm بتنظيف نظام ملفات الحاوية بعد خروجها. نقوم بتسمية الحاوية باسم polls، حتى نتمكن من رؤيتها عندما نقوم بسرد الحاويات.

اخرج من جلسة SSH لخادمك الأول وانتقل إلى http://FIRST_SERVER_IP/polls في متصفحك للتأكد من أنه يعمل كما هو متوقع. إذا كان بإمكانك عرض واجهة الاستطلاعات، فقد تم إعداد خادم التطبيق الأول بنجاح. دعنا نقوم بإعداد خادم التطبيق الثاني في الخطوة التالية.

الخطوة 2: إعداد خادم التطبيق الثاني

سنقوم باستنساخ الفرع المجهز بـ Docker من التطبيق الذي أنشأناه في درس Building a Django and Gunicorn Application with Docker on Ubuntu التعليمي. يمكنك العثور على مزيد من التفاصيل حول الأوامر التي سنستخدمها هنا من ذلك الدرس التعليمي، أو النسخة الملخصة في Step 1.

يجب أن يكون لديك الخادم الثاني قيد التشغيل، وقمت بإضافة مستخدم sudo غير جذري، وتثبيت Docker كما هو موضح في قسم Prerequisites.

الخطوة التالية هي تكوين هذا الخادم للاتصال بمثيل خادم PostgreSQL. كما هو موضح في الخطوة 1 من الدرس التعليمي Building a Django and Gunicorn Application with Docker on Ubuntu، تحتاج إلى السماح لعنوان IP الخاص بالخادم الثاني عبر ufw وتكوينات PostgreSQL.

أولاً، قم بتسجيل الدخول إلى مثيل خادم قاعدة بيانات PostgreSQL باستخدام مستخدم sudo غير الجذري. لإضافة قاعدة ufw، نفذ الأمر التالي:

بعد ذلك، نفذ هذا الأمر وأضف عنوان IP الخاص بالخادم الثاني إلى ملف مصادقة عميل PostgreSQL:

اقرأ التعليقات لفهم المزيد عن التكوينات. بعد ذلك، أضف هذا السطر تحت قسم hosts، مع تحديد عنوان IP الخاص بك:

احفظ الملف وأغلقه عند الانتهاء من التعديل.

بعد ذلك، أعد تشغيل خدمة PostgreSQL لتطبيق التغييرات:

قم بتسجيل الخروج من مثيل خادم قاعدة بيانات PostgreSQL وتابع تكوين مثيل خادم التطبيق الثاني.

قم بتسجيل الدخول إلى second app server باستخدام ssh. ثم قم باستنساخ فرع django-polls-branch من مستودع django-polls باستخدام الأمر التالي:

انتقل إلى دليل django-polls :

بعد ذلك، قم ببناء الصورة باستخدام الأمر التالي:

بمجرد اكتمال عملية بناء الصورة، قم بتعديل ملف env بقيم التكوين كما هو موضح في Step 1. افتح الملف باستخدام nano:

استبدل نصوص النائب بالقيم الفعلية التي أضفتها في الخطوة 1. تذكر تعديل المتغير DJANGO_ALLOWED_HOSTS بشكل مناسب. احفظ الملف وأغلقه عند الانتهاء. قم بتحديث بيانات اعتماد MinIO الخاصة بك في ملف env  كما فعلت في الخطوة السابقة.

الآن يمكنك تشغيل حاوية التطبيق في الوضع المنفصل باستخدام الأمر التالي:

يبدأ الأمر تشغيل الحاوية ويبقيها تعمل في الخلفية. اخرج من جلسة ssh لخادم التطبيق الثاني وانتقل إلى http://SECOND_SERVER_IP/polls في متصفحك للتأكد من أنه يعمل كما هو متوقع. يجب أن تكون قادرًا على عرض واجهة الاستطلاعات إذا سار كل شيء كما هو متوقع.

لديك الآن خادما تطبيقات يقومان بتشغيل نفس النسخة من تطبيقك. في الخطوة التالية، ستقوم بتكوين حاوية Nginx لتعمل كوكيل عكسي.

الخطوة 3: إعداد حاوية Nginx Docker

Nginx هو أحد أشهر برامج خوادم الويب مفتوحة المصدر في العالم. وهو مسؤول عن ضمان توفر وقابلية توسع المواقع ذات الحركة المرورية الأعلى على الإنترنت. إنه يضمن الأمان وهو متعدد الاستخدامات للغاية. يمكنك استخدامه لـ الوكيل العكسي، والتخزين المؤقت، وموازنة التحميل. لقد قمنا بإعداد تطبيقنا لاستخدام خدمة تخزين كائنات منفصلة للتعامل مع ملفاته الثابتة وملفات الوسائط. وبالتالي، لن نستخدم وظائف التخزين المؤقت لـ Nginx. بدلاً من ذلك، سنستخدم إمكانيات الوكيل العكسي وموازنة التحميل لـ Nginx. سيتلقى خادم Nginx المواجه للأمام حركة المرور الواردة ويوزعها على خوادم تطبيقات الخلفية. بعد ذلك، سيضمن الاتصال الآمن بين العميل والخادم عن طريق تأمين حركة المرور باستخدام شهادات SSL التي تم الحصول عليها من Let’s Encrypt.

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

لنبدأ في تكوين خادم الوكيل. قم بتسجيل الدخول إلى خادم Ubuntu الرابع الذي قمت بإعداده لاستخدامه كوكيل Nginx وأنشئ دليل تكوين:

افتح ملف تكوين باستخدام nano داخل الدليل:

بعد ذلك، أضف التكوين التالي إلى الملف:

في ملف التكوين هذا، نحدد server, upstream، و location لتوجيه Nginx لإعادة توجيه طلبات HTTP إلى HTTPS وتوزيع الطلبات بين خادمي التطبيقات اللذين قمنا بإعدادهما في الخطوة 1 و الخطوة 2. يمكنك العثور على معلومات عامة حول بنية ملف تكوين Nginx من وثائقهم الرسمية.

لقد درسنا ملفات التكوين المقدمة من Docker Hub وثائق صورة Nginx, Certbot، و Gunicorn للوصول إلى ملف تكوين Nginx البسيط هذا. في حين أن هذا مخصص لأغراض العرض التوضيحي وتشغيل إعداداتنا فقط، إلا أنه يمكنك استكشاف وتجربة تكوينات أخرى باتباع أدلة Nginx.

تُستخدم كتلة upstream لتعريف مجموعة الخوادم التي ستعالج الطلبات الواردة. يتم إعطاء اسم للمجموعة ويتم استدعاؤه بواسطة توجيه proxy_pass. لقد قمنا بتسمية الكتلة باسم django وحددنا عناوين IP لخادمي تطبيقات الخلفية:

لقد قمنا أيضًا بتعريف 3 كتل خادم. تلتقط كتلة الخادم الأولى جميع الطلبات التي لا تطابق نطاقك وترجع 444 رمزًا (يغلق الاتصال دون إرسال استجابة إلى العميل وبالتالي يمنع الطلبات الضارة أو المشوهة). يتم التعامل مع طلب HTTP المباشر إلى عنوان IP الخاص بخادمك بواسطة هذه الكتلة نظرًا لأنه تم تعريفها على أنها default_server:

تتعامل كتلة الخادم الثانية مع طلبات HTTP الواردة (منفذ 80) وتوجهها إلى HTTPS (منفذ 443) باستخدام إعادة توجيه HTTP 301:

تتعامل كتلة الخادم الثالثة الآن مع الطلبات. وتحتوي على العديد من التوجيهات، وسنحدد أهميتها أدناه.

لدينا توجيهان يحددان المسارات إلى شهادة TLS والمفتاح كما تم توفيرهما بواسطة Certbot. يتم تثبيت الشهادات في حاوية Nginx عند تشغيلها:

بعد ذلك، لدينا إعدادات الأمان الافتراضية لـ SSL كما يوصي بها Certbot. يمكنك معرفة المزيد من وثائق Nginx الرسمية حول ngx_http_ssl_module. تقدم Mozilla أيضًا بعض المعلومات الإضافية حول الأمان من جانب الخادم. تم أخذ قيمة ssl_ciphers في ملف conf من صفحة Mozilla:

في التوجيهين التاليين، سنحدد الحد الأقصى المسموح به لحجم جسم طلب العميل ونضبط المهلة لاتصالات keep-alive النشطة مع العميل. سيقوم Nginx بإغلاق الاتصالات مع العميل بعد الثواني التي تحددها في توجيه keepalive_timeout. يمكنك العثور على مزيد من المعلومات حول تكوينات Nginx لنشر Gunicorn من الوثائق الرسمية:

في ملف التكوين، قمنا أيضًا بتعريف كتلتين للموقع (location blocks). تتعامل الكتلة الأولى مع وكالة الطلبات كما هو محدد في توجيهات الوكيل (proxy directives). يتم توكيل الطلبات الواردة إلى خوادم upstream django المحددة سابقًا:

يمكنك العثور على مزيد من المعلومات حول توجيهات الوكيل من Nginx Module ngx_http_proxy_module والوثائق الخاصة بـ نشر خادم Gunicorn.

في كتلة الموقع (location block) الثانية، نقوم بتعريف مسار: /well-known/acme-challenge/. وعادةً ما يتم استخدامه بواسطة Certbot للتحقق من اسم المجال الخاص بك مع Let’s Encrypt قبل توفير شهادة SSL أو تجديدها:

هذا كل شيء بالنسبة لملف تكوين Nginx. يمكنك الآن حفظ الملف وإغلاقه بمجرد الانتهاء من التعديل.

يمكن استخدام ملف التكوين الذي قمت بتعريفه للتو لتشغيل حاوية Nginx. ومع ذلك، سيفشل ذلك لأننا لم نقم بتوفير شهادات SSL من Let’s Encrypt. في هذا البرنامج التعليمي، سنستخدم nginx:1.20.2 إصدار صورة Docker رقم 1.20.2 من مستودع صور Nginx الرسمي على Docker Hub.

يمكنك تشغيل الأمر أدناه لتنزيل الصورة والتحقق من أن كل شيء يعمل بشكل صحيح:

ينشئ هذا الأمر حاوية باسم nginx ويقوم بتعيين المنافذ 80 و 443 بين النظام المضيف والحاوية. يقوم العلم --rm بإزالة أي حاويات وسيطة بعد نجاح عملية البناء. نستخدم العلم -v لتركيب ملف التكوين داخل الحاوية في /etc/nginx/conf.d/nginx.conf وهو دليل تكوينات Nginx الافتراضي. يتم تركيبه في وضع القراءة فقط باستخدام العلم ro لمنع حاوية Nginx من تعديله. نقوم بتعيين دليل webroot الافتراضي وتركيبه كـ /var/www/html. وننتهي بتوجيه Docker لاستخدام صورة nginx:1.20.2 لهذا البناء. دعنا نحصل على شهادة ومفتاح TLS/SSL من Let’s Encrypt في الخطوة التالية.

الخطوة 4: توفير شهادة SSL/TLS من Let’s Encrypt وتكوين التجديد التلقائي لـ Certbot

Certbot في توفير شهادات TLS مجانية من Let’s Encrypt بالإضافة إلى إدارة تجديدها التلقائي قبل انتهاء صلاحيتها. يعمل هذا على تحسين أمان مواقع الويب الخاصة بك ويضمن تقديمها عبر HTTPS. وتماشيًا مع الحفاظ على بنيتنا في حاويات، سنستخدم صورة Certbot Docker لسحب شهادات SSL/TLS وتكوين التجديد التلقائي. تأكد من أن لديك Docker مثبتًا على خادم الوكيل الخاص بك وفقًا لإرشادات المتطلبات الأساسية.

يجب أن يكون لديك أيضًا سجل DNS A لاسم المجال المسجل الخاص بك يشير إلى عنوان IP الخاص بخادم الوكيل. يمكنك التحقق من ذلك عن طريق تشغيل صورة certbot Docker وتمرير العلم --staging :

سيقوم الأمر بتنزيل صورة Certbot وتشغيلها في الوضع التفاعلي. هذا يعني أنها ستأتي مع واجهة تفاعلية (shell)، مما يسمح لك بإدخال بعض التفاصيل. يقوم بتعيين المنفذ 80 الخاص بالمضيف إلى المنفذ 80 داخل الحاوية. نستخدم العلم -v لتركيب دليلين من المضيف داخل الحاوية: /etc/letsencrypt/ و /var/lib/letsencrypt/. العلم --standalone تحدد هذه العلامة أننا نريد تشغيل صورة Certbot دون استخدام Nginx. وأخيرًا، لدينا --staging التي ستجعل Certbot يعمل على خوادم التجريب (staging) ويتحقق من اسم النطاق الخاص بك.

أدخل عنوان بريدك الإلكتروني واقبل شروط الخدمة عند مطالبتك بذلك. ما يلي هو مخرجات التحقق الناجح:

الخطوات التالية:

سيلزم تجديد الشهادة قبل انتهاء صلاحيتها. يمكن لـ Certbot تجديد الشهادة تلقائيًا في الخلفية، ولكن قد تحتاج إلى اتخاذ خطوات لتمكين هذه الوظيفة. تحقق من هذا الرابط للحصول على التعليمات.

يمكنك عرض الشهادة باستخدام الأمر cat :

يجب أن يعرض الأمر أعلاه شهادتك في الطرفية. بمجرد التأكد من أن Certbot قد قام بتوفير شهادتك، يمكنك الآن اختبار تكوين Nginx الذي قمت بإنشائه في الخطوة 3. قم بتنفيذ أمر Docker أدناه لبدء تشغيل حاوية Nginx:

في هذا الأمر، استخدمنا العلامة -v لربط مسار مجلدات شهادات Let’s Encrypt SSL/TLS.

عندما تعمل الحاوية وتكون قيد التشغيل، افتح صفحة الويب في متصفحك: http://example_domain.com. من المحتمل أن ترى تحذيرًا يفيد بأن موقع الويب غير آمن:

هذا لأننا قمنا فقط بتوفير شهادات تجريبية/اختبارية وليست شهادات production من Let’s Encrypt. لنحصل على شهادات الإنتاج عن طريق تنفيذ أمر Certbot التالي بدون العلامة --staging :

في المطالبة، أكد أنك تريد تجديد واستبدال الشهادة الحالية بكتابة 2 واضغط على ENTER. من شأن هذا توفير شهادة جاهزة للإنتاج. يمكنك الآن تشغيل حاوية Nginx ويجب أن يعمل كل شيء بشكل جيد:

بمجرد تشغيل الحاوية، افتح صفحة الويب في متصفحك: http://example_domain.com مرة أخرى. لاحظ أنه يتم إعادة توجيه متصفحك إلى HTTPS حتى لو وضعت HTTP. هذا يعني أن خادمنا في تكوين Nginx بالإضافة إلى شهادات SSL/TLS الموفرة يعملان بشكل جيد. انتقل إلى مسار polls  مسار http://example_domain.com/polls نظرًا لأنه ليس لدينا مسار محدد للمسار الرئيسي /. يجب أن ترى واجهة الاستطلاعات:

حتى الآن، قمت بتكوين بنية جاهزة للإنتاج بنجاح. لقد قمت بتنفيذ خادمي خلفية سيعالجان الطلبات الواردة الموجهة من خادم الوكيل. سيتعامل خادم الوكيل مع موازنة التحميل وتأمين حركة المرور باستخدام شهادات TLS المقدمة.

ومع ذلك، يجب أن تضع في اعتبارك أن شهادات Let’s Encrypt تنتهي صلاحيتها في غضون 90 يومًا. وبالتالي، يجب عليك تجديدها قبل مرور 90 يومًا. نظرًا لأن حاوية Nginx ستكون قيد التشغيل، يجب عليك استخدام وضع webroot بدلاً من وضع standalone عند تنفيذ أمر certbot لتجديد الشهادة. تذكر أنك قمت بتحديد دليل /var/www/html/.well-known/acme-challenge/ في ملف تكوين Nginx في الخطوة 3. سيستخدم Certbot هذا المسار لتخزين ملفات التحقق. أيضًا، سيستدعي عميل Let’s Encrypt هذا المسار مع طلبات التحقق عندما تحاول تجديد الشهادات. بمجرد انتهاء تنفيذ أمر التجديد، يمكنك إعادة تحميل Nginx لتطبيق التغييرات.

قم بإنهاء الحاوية بالضغط على CTRL+C في الطرفية الخاصة بك، ودعنا نقوم بتشغيلها مرة أخرى في الوضع المنفصل باستخدام علامة -d :

سيؤدي هذا إلى ترك حاوية Nginx تعمل في الخلفية. دعنا نختبر إجراء تجديد الشهادة باستخدام علامة --dry-run عن طريق تنفيذ الأمر أدناه:

في هذا الأمر، قمنا بتحديد المكون الإضافي --webroot بالإضافة إلى المسار المستخدم لطلبات التحقق باستخدام علامة -w. نحدد أيضًا علامة --dry-run للتحقق من إجراء التجديد التلقائي دون توفير شهادة بالفعل.

يجب أن ترى مخرجات مماثلة عند نجاح المحاكاة:

كلما قمت بتجديد شهادة لتطبيقك قيد التشغيل، يجب عليك إعادة تحميل Nginx لتبدأ الحاوية في استخدام الشهادة الجديدة. يقوم أمر Docker التالي بإعادة تحميل حاوية nginx (تذكر أننا قمنا بتسمية الحاوية باسم nginx):

يرسل الأمر إشارة HUP Unix إلى عملية Nginx التي تعمل داخل حاوية Docker لـ nginx. يؤدي هذا إلى قيام Nginx بإعادة تحميل تكويناته والبدء في استخدام الشهادات المجددة.

نظرًا لأن لدينا TLS/SSL مثبتًا على خادم الوكيل الخاص بنا، ويتم تقديم موقعنا الإلكتروني باستخدام HTTPS، فإننا نحتاج الآن إلى تأمين خوادم تطبيقات الخلفية لدينا للسماح فقط بالطلبات القادمة من خادم الوكيل.

الخطوة 5: تأمين خوادم Django الخلفية من الوصول الخارجي

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

في هذا البرنامج التعليمي، تتم حماية خوادم Gunicorn في الخلفية بواسطة Nginx نظرًا لأنها ليست مخصصة لمواجهة الجمهور مباشرة. خادم وكيل Nginx يشبه البوابة لخوادم الخلفية، مما يمنع العملاء الخارجيين من الوصول مباشرة إلى خوادم تطبيقات الخلفية. يجب عليك التأكد من أن جميع الطلبات تمر عبر خادم الوكيل. ومع ذلك، فإن Docker لديه مشكلة حيث يتجاوز ufw قواعد جدار الحماية ويفتح المنافذ خارجيًا، مما قد يترك بنيتك التحتية غير آمنة. هذا واضح بالفعل نظرًا لأننا قمنا بإعداد خوادم التطبيقات الخاصة بنا في الخطوة 1 و الخطوة 2 دون السماح بالمنفذ 80 في قواعد ufw. ومع ذلك، لا يزال بإمكانك الوصول إلى صفحات الويب عند زيارة أي من عناوين IP العامة للخادم في المتصفح. إحدى الطرق التي يمكنك من خلالها إصلاح هذه المشكلة هي استخدام iptables مباشرة دون المرور عبر ufw. يمكنك قراءة Docker و iptables المستندات الرسمية لمعرفة المزيد. طريقة أخرى موصى بها هي استخدام جدران الحماية السحابية.

دعنا نعدل تكوينات UFW لمنع الوصول الخارجي إلى جميع المنافذ التي ربما تم فتحها بواسطة Docker. عندما قمنا بربط منفذ المضيف 80 بمنفذ حاوية Docker 8000 باستخدام العلامة -p 80:8000 في أمر Docker، قمنا أيضًا دون قصد بفتح المنفذ 80 على الجهاز المضيف. يمكنك تعطيل هذا الوصول عن طريق تعديل تكوين UFW كما هو موضح في مستودع ufw-docker README.

دعنا نقوم بالتغيير لخادم تطبيق Django الأول. قم بتسجيل الدخول إلى الخادم وافتح الملف الموجود في /etc/ufw/after.rules باستخدام nano كمستخدم sudo:

يحتوي الملف على قواعد ufw التالية:

أضف كتلة سطور تكوين UFW التالية إلى أسفل الملف:

تمنع القواعد التي أضفتها الوصول العام إلى المنافذ التي يفتحها Docker. علاوة على ذلك، فهي تسمح بالوصول من 10.0.0.0/8, 172.16.0.0/12، و 192.168.0.0/16 نطاقات عناوين IP الخاصة. يمكنك قراءة المزيد من التفاصيل حول القواعد من ufw-docker README. احفظ الملفات وأغلقها عند الانتهاء من التعديل. يجب أن يعمل هذا الإعداد إذا كنت قد قمت بإعداد شبكة سحابية خاصة افتراضية (VPC)، مع وجود جميع خوادمك الثلاثة في الـ VPC، ثم قمت بتحديد عناوين IP الخاصة لخوادم Django في توجيه upstream الخاص بـ Nginx تكوين ملف.

ومع ذلك، فقد استخدمنا عناوين IP عامة وقد لا يكون لدينا VPC. لذلك، تحتاج إلى إضافة قاعدة إلى ufw للسماح بمرور حركة المرور من خادم وكيل Nginx عبر المنفذ 80 لكلا خادمي تطبيق Django. يمكنك إضافة قاعدة سماح إلى ufw تحدد عنوان IP الخاص بالخادم إلى المنفذ 80 باستخدام الأمر التالي:

بمجرد الانتهاء من التعديلات، أعد تشغيل خادم تطبيق Django لتطبيق التغييرات لأن تشغيل sudo ufw reload يبدو أنه يفشل فقط في تطبيق التغييرات:

عند إعادة تشغيل الخادم، قم بتشغيل الحاوية كما فعلت في الخطوة 1 أو الخطوة 2:

بعد ذلك، جرب زيارة عنوان IP لخادم Django الأول في المتصفح لمعرفة ما إذا كان يعرض واجهة Polls: http://FIRST_SERVER_IP/polls. سيفشل ذلك. الآن، قم بتسجيل الخروج من الخادم الأول وكرر الخطوات التي قمت بها هنا للخادم الثاني. افتح /etc/ufw/after.rules باستخدام nano كمستخدم sudo:

كما فعلت سابقًا، قم بالتمرير إلى الأسفل وأضف كتلة تكوينات UFW:

احفظ الملف وأغلقه بمجرد إضافة الكتلة البرمجية أعلاه.

بعد ذلك، أضف قاعدة سماح إلى ufw تحدد IP الخاص بالخادم المصدر إلى المنفذ 80 باستخدام الأمر التالي:

أعد تشغيل الخادم لتطبيق التغييرات:

عندما يعود الخادم للعمل، قم بتشغيل الحاوية مرة أخرى باستخدام الأمر:

اختبر ما إذا كان بإمكانك عرض واجهة الاستطلاعات بالانتقال مباشرة إلى عنوان IP الخاص بالخادم الثاني: http://SECOND_SERVER_IP/polls. يجب أن يفشل هذا أيضًا.

هذه البنية التحتية جاهزة الآن للاختبار. يمكنك زيارة https://example_domain_here/polls لعرض واجهة الاستطلاعات الافتراضية من متصفحك. هذا يعني أن خادم وكيل Nginx لا يزال لديه حق الوصول إلى خوادم Django الخلفية.

الخاتمة

في هذا الدليل، أوضحنا لك كيفية تنفيذ بنية تحتية قابلة للتوسع باستخدام حاويات Docker. تتضمن البنية التحتية خادم قاعدة بيانات PostgreSQL منفصل، وخادمي تطبيقات خلفيين، وخادم وكيل Nginx لموازنة التحميل وتوزيع حركة المرور عبر الخادمين. بينما اعتمدنا في تطبيقنا على تطبيق Django Polls، يمكنك تخصيص هذه البنية لمختلف التطبيقات باستخدام أطر عمل مختلفة، مثل Node.js, Laravel، وما إلى ذلك.

هذا دليل إرشادي أساسي لمساعدتك على البدء. بعض التحسينات التي يمكنك إضافتها هي استضافة صورتك على مستودع صور مثل Docker Hub مما يسمح بتوزيع الصورة بسهولة على خوادم متعددة. يمكنك أيضًا إضافة مسارات التكامل والنشر المستمر لبناء الصور واختبارها ونشرها تلقائيًا في خوادم التطبيقات عند حدوث أي حدث. على سبيل المثال، قد يكون الحدث هو دفع كود جديد إلى فرع محدد في مستودع git. قد ترغب أيضًا في أتمتة ما يحدث عندما تواجه الحاوية خطأً. توفر مستندات Docker الرسمية دليلاً إرشاديًا جيدًا حول بدء تشغيل الحاويات تلقائيًا في حالة حدوث أخطاء أو إعادة تشغيل النظام.

حوسبة سعيدة!

author

Hark Labs

المؤلف · CloudSigma

Preslav Dobrev هو مصمم إبداعي في CloudSigma، يركز على هوية أعمال متسقة باستخدام قنوات التسويق التقليدية والمبتكرة. هو بارع في دمج الرؤية الفنية مع التسويق الاستراتيجي لخلق سرد قصصي مؤثر للعلامة التجارية.

التعليقات

لا توجد تعليقات بعد. كن أول من يعلق.