مقدمة
WordPress هو أحد أشهر أنظمة إدارة المحتوى (CMS) المتاحة. إحصائيًا، يقوم بتشغيل أكثر من 39% من جميع مواقع الويب التي تراها على شبكة الإنترنت العالمية. إنه خيار شائع بسبب قابليته للتوسيع من خلال الإضافات ونظام القوالب المرن الخاص به. يتيح لك تغيير مظهره في ثوانٍ. علاوة على ذلك، يمكن إدارة النظام من خلال واجهة الويب دون الحاجة إلى الكثير من المعرفة التقنية.
بالإضافة إلى ذلك، فإن WordPress مجاني ومفتوح المصدر ومبني على قاعدة بيانات MySQL مع معالجة PHP. يمكنك نشر WordPress على حزمة LAMP (Linux و Apache و MySQL و PHP) أو حزمة LEMP (Linux و Nginx و MySQL و PHP). ومع ذلك، فقد تبين أن إعداد هذه الحزمة يستغرق وقتًا طويلاً في كل مرة تريد فيها النشر.
لحسن الحظ، فإن طرق تقديم البرمجيات الحديثة مثل الحوسبة السحابية, Docker، و Docker Compose قد سهلت تجربة المطور العامة. تبسط هذه الأدوات عملية إعداد أي حزمة من خلال تجنب عبء تثبيت وتكوين المكونات الفردية في كل مرة تريد فيها نشر تطبيق. بدلاً من ذلك، تكتب ملفات تكوين سيتم استخدامها لسحب وإنشاء الصور وتشغيلها في حاويات Docker، مما يتيح لك نشر تطبيقك بأمر واحد فقط.
الحاويات هي بيئات معيارية خفيفة الوزن، وافتراضية، ومحمولة، ومحددة بالبرمجيات تتيح للبرمجيات العمل بمعزل عن البرمجيات الأخرى التي تعمل على الجهاز المضيف الفعلي. يتيح لك Docker Compose إدارة حاويات متعددة وضمان تواصلها. على سبيل المثال، يجب أن يتواصل الكود المصدري للتطبيق وقاعدة البيانات.
في هذا البرنامج التعليمي، سنقوم بـبناء تطبيق WordPress متعدد الحاويات. يتطلب تطبيق WordPress الكامل ثلاث حاويات: قاعدة بيانات MySQL، وخادم Nginx، والكود المصدري لـ WordPress. نظرًا لأن الأمان يمثل أولوية في مواقع الويب الحديثة، فسنحصل على شهادة SSL من Let’s Encrypt لتأمين تثبيتك. بعد ذلك، سنقوم بإعداد مهمة cron للتحقق بشكل دوري من الشهادات وتجديدها بحيث يتم الحفاظ على أمان موقع الويب الخاص بك باستمرار.
المتطلبات الأساسية
- بما أن هذا برنامج تعليمي عملي، يجب أن يكون لديك تثبيت لنظام التشغيل Ubuntu 20.04 كبيئة تشغيل أولية. يجب أن يكون لديك أيضًا مستخدم غير جذري (non-root) يتمتع بصلاحيات sudo. إليك برنامج تعليمي خطوة بخطوة لمساعدتك في إعداد خادم Ubuntu الخاص بك.
- تحتاج أيضًا إلى تثبيت Docker. يمكنك الرجوع إلى هذا البرنامج التعليمي حول كيفية تثبيت وتشغيل Docker على Ubuntu 18.04.
- تثبيت Docker Compose. يمكنك اتباع الخطوة 1 من البرنامج التعليمي كيفية تثبيت وتكوين Docker Compose على Ubuntu 20.04.
- يلزم وجود اسم نطاق مسجل للحصول على شهادة TLS/SSL من Let’s Encrypt. من أجل هذا البرنامج التعليمي، سنستخدم
example.com. - قم بإعداد سجلات DNS لتوجيه حركة المرور إلى VPS الخاص بك. تحتاج إلى سجلي DNS:
- سجل A مع
example.comيشير إلى عنوان IP العام لخادمك. - سجل A مع
www.example.comيشير إلى عنوان IP العام لخادمك.
- سجل A مع
الخطوة 1: تحديد تكوينات خادم الويب
يحتوي خادم الويب على ملفات موقع الويب الخاص بك ويتيح للمستخدمين الوصول إلى تطبيق الويب الخاص بك. وبالتالي، فمن المناسب فقط أن نحدد في الخطوة الأولى تكوين خادم الويب. سنقوم بتحديد ملف تكوين خادم Nginx والذي سيتضمن كتل مواقع (location blocks) خاصة بـ WordPress. سنقوم أيضًا بتضمين كتل مواقع لتوجيه طلبات التحقق من Let’s Encrypt إلى عميل Certbot للتجديد التلقائي للشهادة.
لنبدأ بإنشاء دليل للمشروع. يمكنك اختيار اسم الدليل الذي تفضله. سنستخدم wordpress_docker لهذا البرنامج التعليمي. أدخل الأمر التالي لإنشاء الدليل والانتقال إليه:
|
1 |
mkdir wordpress_docker && cd wordpress_docker |
بعد ذلك، قم بإنشاء دليل للاحتفاظ بملفات تكوين Nginx باستخدام الأمر:
|
1 |
mkdir nginx-conf |
استخدم nano لفتح الملف بالأمر التالي:
|
1 |
nano nginx-conf/nginx.conf |
في هذا الملف، سنقوم بتعريف التوجيهات الأساسية لتكوين كتلة خادم Nginx. وتشمل هذه التوجيهات اسم الخادم، والمجلد الجذري للمستندات (document root)، وكتل الموقع (location blocks) لتوجيه طلبات ملحق Certbot للحصول على الشهادات، والملفات الثابتة، ومعالجة PHP. يمكنك قراءة دليلنا التعليمي حول كيفية تأمين Nginx باستخدام Let’s Encrypt لمعرفة المزيد. أضف الكود التالي إلى الملف، مع استبدال example.com باسم النطاق المسجل الخاص بك:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
server { listen 80; listen [::]:80; server_name example.com www.example.com; index index.php index.html index.htm; root /var/www/html; location ~ /.well-known/acme-challenge { allow all; root /var/www/html; } location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { log_not_found off; access_log off; allow all; } location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ { expires max; log_not_found off; } } |
دعنا نحدد الأقسام التي قمت بإضافتها:
-
التوجيهات:
listen: يخبر Nginx بالاستماع على المنفذ80. يتيح هذا استخدام ملحق webroot الخاص بـ Certbot لتقديم طلبات الحصول على الشهادات. بمجرد حصولنا على شهادة SSL، سنقوم بتحديث هذا التكوين لاستخدام المنفذ443.server_name: يحدد هذا اسم النطاق الذي يجب أن يتعامل معه هذا التكوين. سيتم توجيه حركة المرور إلى اسم النطاق المحدد هنا إلى كتلة الخادم هذه تحديدًا، وبالتالي إلى مستند الـroot.root: يحدد الدليل الجذري للطلبات الموجهة إلى اسم النقاط أعلاه. عادةً ما يكون هذا هو الدليل الذي يحتوي على ملفات موقعنا الفعلي. لقد قمنا بتعيين الدليل إلى/var/www/html. سيتم إنشاؤه كـ نقطة تثبيت Docker أثناء وقت بناء الحاوية. سنقوم بتحديد التعليمات الخاصة بهذه العملية داخل WordPress Dockerfile.index: يحدد هذا الملفات التي سيتم استخدامها كفهارس أو كنقطة دخول لخادم الويب الخاص بك عند معالجة الطلبات. لقد قمنا بنقل index.php قبل index.html لكي يعطي Nginx الأولوية لـindex.php.
-
Location Blocks:
location ~ /.well-known/acme-challenge: يعالج الطلبات الموجهة إلى الدليل المعروف (well-known) حيث يضيف Certbot ملفًا مؤقتًا للتحقق من أن DNS للنطاق المحدد يوجه إلى الخادم المعين الذي نطلب شهادات SSL منه. هذا هو السبب في أنه يجب عليك إضافة نطاق صالح لكي تعمل هذه الخطوة بدلاً منexample.comالذي نستخدمه في هذا البرنامج التعليمي.location /: يلتقط طلبات URI ويمنح التحكم لـ WordPressindex.phpلطلب الوسيطات للمعالجة.location ~ \.php$: يعالج معالجة PHP ويمرر الطلب إلى حاوية WordPress (سنقوم بتحديد ملف تكوين لهذا في خطوة لاحقة). لقد قمنا بتعريف تكوينات خاصة ببروتول FastCGI هنا لأن صورة Docker الخاصة بـ WordPress ستعتمد على صورة php:fpm . يستخدم Nginx معالج PHP مستقل للطلبات الخاصة بـ PHP. سنستخدم معالجphp-fpmالذي يأتي مع صورة Docker لـphp:fpm.location ~ /\.ht: يعالج ملفات.htaccessالتي لا يستخدمها Nginx. يضمن توجيهdeny allعدم تقديم هذه الملفات مطلقًا لزوار الموقع.location = /favicon.ico, location = /robots.txt: كما هو موضح في التعريف، فإن هذا يمنع تسجيل الطلبات إلى ملفات/favicon.icoو/robots.txt.location ~* \.(css|gif|ico|jpeg|jpg|js|png)$: يوقف تسجيل الطلبات إلى الملفات الثابتة ويضمن تخزينها مؤقتًا لتقليل الحمل على الخادم.
يمكنك الآن حفظ الملف وإغلاقه بالضغط على CTRL+X, Y، ثم ENTER. وبذلك تكتمل الخطوة الأولى.
Step 2: Define Environment Variables
متغيرات البيئة ضرورية لتسهيل الاتصال بين تطبيق WordPress وقاعدة البيانات. كما أنها تضمن استمرار بقاء بيانات التطبيق. تتضمن متغيرات البيئة معلومات حساسة مثل بيانات اعتماد قاعدة البيانات ومعلومات غير حساسة مثل اسم قاعدة البيانات والمضيف.
لأغراض أمنية، من الجيد دائمًا عدم إضافة معلومات حساسة إلى مستودعات المشروع. وبالتالي، بدلاً من تعيين القيم الحساسة في ملف Docker Compose، سنقوم بتحديد بيانات اعتماد MySQL داخل ملفات .env التي لن يتم إرسالها إلى مستودع المشروع وتجنب خطر الكشف العام عنها. داخل مجلد المشروع root ~/wordpress_docker افتح ملف .env :
|
1 |
nano .env |
|
1 2 3 |
MYSQL_ROOT_PASSWORD=your_strong_root_password MYSQL_USER=your_wordpress_database_user MYSQL_PASSWORD=strong_wordpress_database_password |
الشيء التالي الذي يجب عليك فعله هو إضافة ملف .env إلى ملفات .gitignore و .dockerignore لضمان عدم إضافته إلى مستودعاتك أو صور Docker الخاصة بك على التوالي.
هذا ليس ضروريًا لهذا البرنامج التعليمي، ولكن إذا كنت تريد العمل مع Git لإدارة الإصدارات، أدخل الأمر التالي لتهيئة الدليل الحالي كمستودع git:
|
1 |
git init |
افتح ملف .gitignore باستخدام nano:
|
1 |
nano .gitignore |
أضف السطر التالي:
|
1 |
.env |
احفظ الملف وأغلقه. بعد ذلك، افتح ملف .dockerignore باستخدام nano:
|
1 |
nano .dockerignore |
أضف السطر التالي:
|
1 |
.env |
أثناء القيام بذلك، يمكنك اختياريًا إضافة ملفات وأدلة أخرى مرتبطة بتطوير تطبيقك:
|
1 2 3 |
.env .git docker-compose.yml |
احفظ الملف وأغلقه عند الانتهاء. هذا كل شيء بالنسبة لهذه الخطوة. لننتقل إلى تعريف Docker Compose.
Step 3: Configure Services with Docker Compose
يستخدم Docker Compose ملف docker-compose.yml لبناء الصور. يحتوي هذا الملف على تعريفات الخدمة للإعداد الكامل للتطبيق. تعريفات الخدمة هي في الأساس تعليمات لكيفية تشغيل الحاوية. الخدمة هي حاوية قيد التشغيل بالفعل.
يتيح Docker Compose إمكانية تحديد خدمات مختلفة للتطبيقات متعددة الحاويات من خلال ربط الخدمات المتنوعة معًا بشبكات ومساحات تخزين مشتركة. سترى هذا عمليًا حيث سنقوم بتحديد ثلاث حاويات لتطبيقنا: خادم الويب، وتثبيت WordPress، وقاعدة البيانات. سنضيف حاوية رابعة لتشغيل عميل Certbot لتجديد الشهادات.
أدخل الأمر التالي لإنشاء ملف docker-compose.yml :
|
1 |
nano docker-compose.yml |
السطر الأول في ملف docker-compose.yml هو سطر تعريف الإصدار. لقد قمنا بتعيين 3 لملفنا. بعد ذلك، يمكنك البدء في تحديد خدماتك. أضف مقتطف الكود التالي في الملف لتحديد خدمة db :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
version: '3' services: #خدمة MySQL db: image: mysql:8.0 container_name: db restart: unless-stopped env_file: .env environment: - MYSQL_DATABASE=wordpress volumes: - dbdata:/var/lib/mysql command: '--default-authentication-plugin=mysql_native_password' networks: - app-network |
دعونا نناقش ما لدينا في تعريفات خدمة db أدناه:
image: يحدد الصورة التي ستعتمد عليها الحاوية. من الأفضل دائمًا تحديد إصدار معين (mysql:8.0) بدلاً من استخدام علامة الأحدث (mysql:latest) لأن الإصدارات المستقبلية من صور MySQL قد تتعارض مع تطبيقنا إذا قمنا بإعادة بناء هذه الصورة. يمكنك العثور على مزيد من المعلومات حول أفضل ممارسات Dockerfiles على وثائق Dockerfile الرسمية.container_name: نحدد اسم الحاوية هنا.restart: يحدد هذا التوجيه سلوك إعادة تشغيل الحاوية. الافتراضي هوnoولكننا قمنا بتعيينه ليعاد تشغيله دائمًاrestartما لم يتم إيقافه يدويًا.env_file: يُستخدم هذا التوجيه لتحديد موقع الملف الذي يحتوي على متغيرات البيئة (.env) المستخدمة بواسطة تطبيقنا.environment: يُستخدم لتحديد متغيرات بيئة إضافية. في هذا البرنامج التعليمي، قمنا بتحديد متغيرMYSQL_DATABASEللاحتفاظ باسم قاعدة البيانات لتطبيقنا. يمكن تضمين اسم قاعدة البيانات فيdocker-compose.yml.volumes: يُستخدم لتحديد مواقع الربط (mount). في مثالنا، قمنا بربط مساحة تخزين مسماة volume تسمى dbdata بدليل/var/lib/mysqlعلى الحاوية، وهو عادةً دليل البيانات القياسي لـ MySQL.command: يحدد هذا التوجيه أمرًا سيتجاوز تعليمات CMD الافتراضية للصورة. لقد أضفنا خيارًا إلى أمرmysqldالقياسي لصورة Docker والذي يبدأ تشغيل خادم MySQL داخل الحاوية. الخيار الذي أضفناه هو--default-authentication-plugin=mysql_native_password، والذي يقوم بتحديث مكون المصادقة الإضافي الافتراضي لـ MySQL لاستخدام مصادقة كلمة المرور (mysql_native_password). هذا ضروري ليعمل تطبيق PHP (تطبيق WordPress) لأنه يستخدم اسم مستخدم وكلمة مرور للوصول إلى قاعدة البيانات. في إصدارات MySQL الأحدث، تغير مكون المصادقة الإضافي الافتراضي. ومع ذلك، تستخدم معظم التطبيقات مصادقة كلمة المرور. وبالتالي، يجب عليك تغيير هذا الإعداد ليعمل التطبيق.networks: يُستخدم هذا التوجيه لتحديد أن خدمةdbيجب أن تنضم إلىapp-network، والتي سنقوم بتعريفها مع تقدمنا في البرنامج التعليمي.
بعد ذلك، دعنا نحدد تكوين الخدمة لتطبيق WordPress الخاص بنا. سنطلق على الخدمة و container_name اسم app. أضف مقتطف الكود التالي أسفل تعريف خدمة db، مع مراعاة المسافة البادئة المناسبة:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#خدمة كود تطبيق WordPress app: depends_on: - db image: wordpress:5.1.1-fpm-alpine container_name: app restart: unless-stopped env_file: .env environment: - WORDPRESS_DB_HOST=db:3306 - WORDPRESS_DB_USER=$MYSQL_USER - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD - WORDPRESS_DB_NAME=wordpress volumes: - app:/var/www/html networks: - app-network |
تمامًا كما فعلنا مع خدمة db، قمنا بتسمية الحاوية الخاصة بنا وتحديد سياسة إعادة التشغيل. تم تعريف بعض الخيارات الإضافية التي أضفناها أدناه:
depends_on: يضمن هذا التوجيه بدء تشغيل الحاويات بترتيب التبعية. في حالتنا، تعتمد حاويةappعلى حاويةdb. وبالتالي، ستبدأ بعد بدء تشغيل حاويةdb. يجب أن يحدث هذا بهذا الترتيب لأن تطبيق WordPress يعتمد على توفر قاعدة بيانات MySQL لكي يعمل.image: كما هو موضح في مقتطف الكود، سنستخدم صورة WordPress إصدار 5.1.1 fpm alpine image. لقد شرحنا عن معالجphp-fpmالذي يتطلبه Nginx لمعالجة PHP. تتولى هذه الصورة ذلك. تساعد صورة alpine المبنية على مشروع Alpine Linux في الحفاظ على حجم الصورة أصغر. إذا كنت بحاجة إلى مزيد من المعلومات حول تنوعات الصور، يمكنك اتباع هذا الرابط لـ صور WordPress على Docker Hub.env_file: يحدد موقع ملف.envالذي يحتوي على بيانات اعتماد قاعدة البيانات.environment: يحدد هذا التوجيه متغيرات بيئة إضافية. بالنسبة لحالتنا، نقوم بتعريف المتغيرات التي يتوقعها WordPress وتعيين قيم المتغيرات لها من ملف.envالخاص بنا. هذه المتغيرات هيWORDPRESS_DB_USER,WORDPRESS_DB_PASSWORD، وWORDPRESS_DB_HOSTالذي يشير إلى خادم MySQL الذي يعمل على حاويةdb، والذي يمكن الوصول إليه من منفذ MySQL الافتراضي3306. أخيرًا، ترىWORDPRESS_DB_NAMEالذي قمنا بتعيينه إلى WordPress. تم تحديد نفس القيمة في تعريف خدمة MySQL في حاوية db:MYSQL_DATABASE=wordpress.volumes: يقوم هذا التوجيه بتركيب وحدة تخزين تسمى app في نقطة التركيب/var/www/html، والتي تم إنشاؤها بواسطة صورة WordPress. تتيح تسمية وحدات التخزين مشاركة كود التطبيق مع الحاويات الأخرى.networks: أخيرًا، نضيف حاوية app إلىapp-networkلضمان اتصالها بالحاويات الأخرى على الشبكة.
سيكون هذا كل شيء بالنسبة لحاوية خدمة app لصورة WordPress. دعنا الآن نحدد خدمة webserver لصورة Nginx. أولاً، أضف مقتطف الكود التالي أسفل تعريف خدمة app في ملف docker-compose.yml الخاص بك:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#خدمة ويب خادم Nginx webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network |
لقد شرحنا بالفعل خيار depends_on. في حالة خدمة webserver هذه، ستبدأ الحاوية بعد بدء تشغيل حاوية app. تعتمد حاوية خادم الويب على صورة alpine Nginx. ولديها سياسة إعادة تشغيل مماثلة لتعريفات الخدمة السابقة. تشمل الخيارات الأخرى في تعريف خدمة webserver ما يلي:
ports: يربط المنافذ بين الجهاز المضيف والحاوية. في الخطوة 1، قمنا بتعريف المنفذ80في ملفnginx.conf. هذا المنفذ مخصص للمنفذ80على الحاوية.volumes: لدينا مزيج من bind mounts والمجلدات المسماة تحت هذا الخيار:app:/var/www/html: يقوم تعريف المجلد هذا بتثبيت تطبيق WordPress في دليل/var/www/htmlالذي قمنا بتعيينه سابقًا كجذر في كتلة خادم Nginx../nginx-conf:/etc/nginx/conf.d: يقوم هذا التعريف بربط دليل تكوين Nginx على الجهاز المضيف بدليل تكوين Nginx الذي حددناه للحاوية. وبالتالي، تنعكس أي تغييرات على الجهاز المضيف تلقائيًا في الحاوية.certbot-etc:/etc/letsencrypt: يقوم هذا التعريف بتثبيت شهادات ومفاتيح Let’s Encrypt الخاصة بالنطاق في الدليل المناسب على الحاوية.
networks: كما هو الحال في تعريفات الخدمة السابقة، يضيف التوجيهnetworksخدمة webserver إلىapp-networks.
بما أننا انتهينا من تعريف خادم الويب، فلنضف تعليمات لخدمة Certbot. سيتولى هذا الحصول على شهادات TLS/SSL الخاصة بك من Let’s Encrypt. إذا كنت ترغب في معرفة المزيد حول تأمين خادم Nginx، فإن هذا البرنامج التعليمي حول كيفية تأمين Nginx باستخدام Let’s Encrypt يعد مصدرًا جيدًا.
بعد ذلك، أضف مقتطف الكود التالي أسفل خدمة webserver. تذكر تعيين اسم النطاق وعنوان البريد الإلكتروني الصحيحين:
|
1 2 3 4 5 6 7 8 9 10 |
#خدمة certbot certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --staging -d example.com -d www.example.com |
ستبدأ صورة certbot فقط بعد بدء تشغيل webserver، بسبب التوجيه depends_on. سيقوم Docker Compose بسحب صورة Certbot من Docker Hub كما هو محدد.
ضمن تعريف المجلدات (volumes)، ستشارك حاوية Certbot شهادات النطاق والمفتاح في certbot-etc مع حاوية Nginx webserver ورمز التطبيق مع حاوية app.
ضمن تعريف command، قمنا بتحديد أمر فرعي لتشغيل أمر Certbot الافتراضي للحاوية certonly command مع خيارات إضافية كما هو موضح أدناه:
-
--webroot: يحدد استخدام مكون webroot الإضافي الذي يضع الملفات في مجلد webroot للمصادقة.--webroot-path: يحدد مسار دليل webroot.--agree-tos: يحدد أنك توافق على شروط خدمة ACME.--no-eff-email: يحدد أنك لا تريد مشاركة بريدك الإلكتروني مع EFF. يمكنك حذف هذا إذا كنت تريد المشاركة.--staging: يخبر Certbot أنك تريد أولاً الحصول على شهادات اختبار من بيئة اختبار Let’s Encrypt لاختبار التكوين الخاص بك قبل الحصول على الشهادة الفعلية. لدى Let’s Encrypt حدود على معدل طلبات النطاق. وبالتالي، فإن اختبار التكوين الخاص بك أولاً سيساعدك على تجنب فرض قيود على نطاقك.-d: يأخذ هذا الخيار أسماء النطاقات لطلب الشهادة. في هذا البرنامج التعليمي، قمنا بتضمينexample.comوwww.example.com. يرجى تحديد نطاقك المسجل الفعلي.
ملف docker-compose.yml الخاص بنا شبه مكتمل. ومع ذلك، يجب عليك أيضًا إضافة تعريفات الشبكة والمجلدات أسفل خدمة Certbot:
|
1 2 3 4 5 6 7 8 9 10 |
#المجلدات volumes: certbot-etc: app: dbdata: #الشبكات networks: app-network: driver: bridge |
يحدد مفتاح volumes المجلدات التي سيتم مشاركتها مع جميع الخدمات (الحاويات) المحددة في ملف compose هذا: certbot-etc, app، و dbdata. يتم تخزين محتويات المجلدات التي ينشئها Docker في دليل يديره Docker على نظام ملفات الجهاز المضيف: /var/lib/docker/volumes/. ثم يتم ربط محتويات كل وحدة تخزين بأي حاوية تستخدم هذه الوحدة. وهذا يتيح مشاركة البيانات والتعليمات البرمجية بين الحاويات.
إنّ networks يحدد شبكة الجسر التي تسمح بالاتصال بين الحاويات. يمكن للحاويات الموجودة على نفس شبكة الجسر مثل webserver و db الاتصال بشكل آمن عبر المنافذ دون تعريض حركة المرور للشبكة الخارجية. نحن نقوم فقط بفتح المنفذ 80 للسماح بالوصول إلى صفحات موقع الويب الأمامية.
سيبدو ملف docker-compose.yml الكامل كالتالي:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
version: '3' services: #خدمة MySQL db: image: mysql:8.0 container_name: db restart: unless-stopped env_file: .env environment: - MYSQL_DATABASE=wordpress volumes: - dbdata:/var/lib/mysql command: '--default-authentication-plugin=mysql_native_password' networks: - app-network #خدمة كود تطبيق WordPress app: depends_on: - db image: wordpress:5.1.1-fpm-alpine container_name: app restart: unless-stopped env_file: .env environment: - WORDPRESS_DB_HOST=db:3306 - WORDPRESS_DB_USER=$MYSQL_USER - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD - WORDPRESS_DB_NAME=wordpress volumes: - app:/var/www/html networks: - app-network #خدمة خادم الويب Nginx webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network #خدمة certbot certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --staging -d example.com -d www.example.com #وحدات التخزين volumes: certbot-etc: app: dbdata: #الشبكات networks: app-network: driver: bridge |
يمكنك حفظ الملف وإغلاقه. في الخطوة التالية، سنقوم بتشغيل واختبار الحاوية وطلبات الشهادات.
الخطوة 4: تشغيل الحاويات والحصول على شهادات SSL
الميزة الأكبر لـ Docker Compose هي أنه بمجرد تحديد جميع خدماتك في ملف docker-compose.yml ملف، يمكنك بدء تشغيل جميع الحاويات بأمر واحد فقط: docker-compose up. يقوم الأمر بتشغيل كل التعليمات المحددة. إذا كانت طلبات النطاق ناجحة، فيجب أن تكون قادرًا على رؤية حالة الخروج الصحيحة في الطرفية الخاصة بك. أدخل الأمر التالي لإنشاء الحاويات. الـ -d مخصصة لتشغيل الحاويات في الخلفية:
|
1 |
docker-compose up -d |
إذا رأيت مخرجات مثل تلك الموجودة في لقطة الشاشة أدناه، فهذا يعني أنه تم إنشاء الخدمات بنجاح:
لتأكيد حالة الخدمات، قم بتشغيل الأمر docker-compose ps :
|
1 |
docker-compose ps |
تكون مخرجات الأمر كما هو موضح أدناه إذا كان كل شيء ناجحًا. يجب أن تكون حالة حاويات app, db، و webserver هي up، ويجب أن تكون حالة حاوية certbot هي Exit0 :
إذا رأيت أي شيء آخر غير Up في عمود الحالة لـ app, db أو webserver, أو حالة Exit ليست 0 لحاوية certbot، فهذا يعني أن هناك خطأ ما قد حدث. يمكنك التحقق من سجلات كل حاوية باستخدام الأمر docker-compose logs، وتحديد الـ service_name:
|
1 |
docker-compose logs service_name |
على سبيل المثال، يمكنك التحقق من سجلات حاوية certbot عن طريق إدخال الأمر التالي:
|
1 |
docker-compose logs certbot |
للتحقق مما إذا كانت الشهادات قد تم تركيبها في حاوية webserver، استخدم الأمر docker-compose exec :
|
1 |
docker-compose exec webserver ls -la /etc/letsencrypt/live |
إذا استخدمت اسم نطاق مسجل بالفعل غير example.com وكانت طلبات الشهادة ناجحة، فيجب أن ترى مخرجات مشابهة لهذا:
بمجرد تأكيد نجاح طلب الشهادة، يمكنك تعديل ملف docker-compose.yml وإزالة علامة --staging. افتح الملف باستخدام nano:
|
1 |
nano docker-compose.yml |
قم بالتمرير لأسفل إلى قسم تعريف خدمة Certbot، في خيار الأمر واستبدل علامة --staging بعلامة --force-renewal. يخبر هذا Certbot بأنك تطلب تجديد شهادة لنفس النطاق. يجب أن يبدو تعريف خدمة Certbot الآن كما يلي:
|
1 2 3 4 5 6 7 8 9 10 |
#certbot service certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com |
احفظ الملف عندما تنتهي من التعديل.
أدخل الأمر التالي لإعادة إنشاء حاوية certbot. علامة --no-deps المضمنة تخبر Compose بتخطي إعادة تشغيل خدمة خادم الويب لأنها تعمل بالفعل:
|
1 |
docker-compose up --force-recreate --no-deps Certbot |
يُظهر الأمر لقطة الشاشة التالية، مما يوضح أن طلب الشهادة كان ناجحًا:
هذا كل شيء بالنسبة لهذه الخطوة. في الخطوة التالية، ستقوم بتعديل ملف تكوين Nginx لتضمين شهادة SSL.
الخطوة 5: تمكين SSL في تكوين Nginx وتعريف الخدمة
لجعل Nginx يخدم حركة المرور عبر بروتوكول SSL الآمن، ستقوم أولاً بتعديل ملف تكوين Nginx لإضافة إعادة توجيه من HTTP إلى HTTPS. بعد ذلك، تحتاج إلى تحديد مواقع الشهادة والمفتاح، وأخيرًا إضافة معلمات الأمان والرؤوس.
قبل تعديل ملف التكوين، يجب عليك الحصول على معلمات أمان Nginx الموصى بها من مستودع GitHub الخاص بـ Certbot باستخدام curl بالأمر التالي:
|
1 |
curl -sSLo nginx-conf/options-ssl-nginx.conf |
يتم تشغيل الأمر وحفظ المعلمات التي يسحبها في ملف يسمى options-ssl-nginx.conf، داخل nginx-conf . قم بإزالة ملف تكوين Nginx حتى نتمكن من إنشاء ملف جديد باستخدام الأوامر التالية:
|
1 2 |
rm nginx-conf/nginx.conf nano nginx-conf/nginx.conf |
في ملف nginx.conf الفارغ الآن، أضف الكود التالي الذي يتضمن إعادة توجيه من HTTP إلى HTTPS، و SSL، ورؤوس الأمان. كما فعلت سابقًا، استبدل نطاق example.com بنطاقك المسجل الخاص:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
server { listen 80; listen [::]:80; server_name example.com www.example.com; location ~ /.well-known/acme-challenge { allow all; root /var/www/html; } location / { rewrite ^ https://$host$request_uri? permanent; } } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com www.example.com; index index.php index.html index.htm; root /var/www/html; server_tokens off; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; include /etc/nginx/conf.d/options-ssl-nginx.conf; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-الأمان-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always; # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; # قم بتمكين أمن النقل الصارم فقط إذا كنت تفهم الآثار المترتبة على ذلك location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { log_not_found off; access_log off; allow all; } location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ { expires max; log_not_found off; } } |
في كتلة الخادم الأولى التي تتعامل مع الطلبات غير الآمنة باستخدام المنفذ 80، نحدد الـ webroot لطلبات تجديد Certbot. ونقوم أيضًا بتضمين توجيه إعادة التوجيه الذي يعيد توجيه طلبات HTTP إلى HTTPS.
تتعامل كتلة الخادم الثانية مع حركة مرور HTTPS الآمنة القادمة على المنفذ 443. كما ترى، نقوم أيضًا بتمكين SSL و HTTP2. يعمل HTTP/2 على تحسين أداء خادمك. يمكنك قراءة المزيد عن ذلك في مستندات Nginx الرسمية حول HTTP/2.
في هذه الكتلة، حددنا أيضًا أن يتضمن Nginx مواقع شهادة SSL والمفتاح، بالإضافة إلى معلمات أمان Certbot الموصى بها والتي قام curl بحفظها في دليل nginx-conf/options-ssl-nginx.conf.
تخدم ترويسات الأمان الإضافية تحسين تقييمات موقعك الإلكتروني على مواقع اختبار الأمان مثل Security Headers و SSL Labs. يمكنك اتباع الروابط الموجودة على هذه الترويسات لمعرفة المزيد: X-Frame-Options, Referrer Policy, X-Content-Type-Options, X-XSS-Protection, Content-Security-Policy. لقد قمنا بتعليق ترويسة HTTP Strict Transport Security (HSTS). لك الحرية في القراءة عن وظيفة التحميل المسبق (preload) الخاصة بها وتحديد ما إذا كنت تريد تمكينها.
باقي التوجيهات مثل root, index, وكتل المواقع الخاصة بـ WordPress تظل كما تمت مناقشتها في الخطوة 1. يمكنك الآن حفظ الملف وإغلاقه عند الانتهاء من التعديل.
الآن بعد أن قمنا بتمكين حركة مرور HTTPS التي تستخدم المنفذ 443,، يجب علينا أيضًا تمكين المنفذ في تعريف الخدمة لخادم الويب. أدخل الأمر التالي لفتح ملف docker-compose.yml باستخدام nano:
|
1 |
nano docker-compose.yml |
في قسم خادم الويب تحت خيار المنافذ (ports)، أضف ربطًا للمنفذ 443 كما هو موضح أدناه:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" - "443:443" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network |
يجب أن يبدو ملف docker-compose.yml الكامل الآن كما يلي:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
version: '3' services: #خدمة MySQL db: image: mysql:8.0 container_name: db restart: unless-stopped env_file: .env environment: - MYSQL_DATABASE=wordpress volumes: - dbdata:/var/lib/mysql command: '--default-authentication-plugin=mysql_native_password' networks: - app-network #خدمة كود تطبيق WordPress app: depends_on: - db image: wordpress:5.1.1-fpm-alpine container_name: app restart: unless-stopped env_file: .env environment: - WORDPRESS_DB_HOST=db:3306 - WORDPRESS_DB_USER=$MYSQL_USER - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD - WORDPRESS_DB_NAME=wordpress volumes: - app:/var/www/html networks: - app-network #خدمة خادم الويب Nginx webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" - "443:443" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network #خدمة certbot certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com #المجلدات volumes: certbot-etc: app: dbdata: #الشبكات networks: app-network: driver: bridge |
بمجرد التأكد من أن كل شيء يبدو صحيحًا، احفظ الملف وأغلقه. بعد ذلك، قم بتشغيل الأمر التالي لإعادة إنشاء webserver خدمة:
|
1 |
docker-compose up -d --force-recreate --no-deps webserver |
|
1 |
docker-compose ps |
الآن بعد أن أصبحت جميع الحاويات الخاصة بك تعمل، من الممكن المتابعة في تكوين WordPress من واجهة الويب.
الخطوة 6: أكمل تكوين WordPress الخاص بك من واجهة الويب
انتقل إلى اسم نطاق الخادم الخاص بك لمتابعة التثبيت. يجب أن تظهر لك الصفحة الرئيسية لإعداد WordPress. ترحب بك لاختيار لغتك قبل المتابعة:
اختر لغتك وانقر فوق متابعة للانتقال إلى الصفحة التالية:
في هذه الصفحة، املأ عنوان موقعك الإلكتروني، واختر اسم مستخدم يسهل تذكره وكلمة مرور قوية. يوصى بعدم استخدام Admin كاسم مستخدم لأسباب أمنية. أدخل بريدك الإلكتروني وانقر على زر تثبيت WordPress لبدء تثبيت WordPress.
بمجرد اكتمال التثبيت، سيتم نقلك إلى شاشة تسجيل الدخول حيث ستدخل اسم المستخدم وكلمة المرور اللذين قمت بتعيينهما. عند إدخال بيانات الاعتماد الصالحة، يجب أن تكون قادرًا على رؤية لوحة تحكم WordPress الخاصة بك:
لقد قمت الآن بتثبيت WordPress بنجاح! بعد ذلك، تحتاج إلى اتخاذ الخطوات اللازمة لضمان تجديد شهادات SSL تلقائيًا.
الخطوة 7: تكوين التجديد التلقائي لشهادة SSL
شهادات Let’s Encrypt TLS/SSL صالحة لمدة 90 يومًا فقط. الأمر متروك لك لإنشاء تكوين تجديد تلقائي لضمان عدم انتهاء صلاحيتها. يمكنك تحقيق ذلك عن طريق إنشاء برنامج نصي وجدولته باستخدام أداة cron job. في هذه الخطوة، سنوضح لك كيفية إنشاء برنامج نصي يقوم بتجديد الشهادات. سنقوم بعد ذلك بجدولته باستخدام أداة cron job لتشغيله بشكل دوري وتجديد الشهادات إذا كانت تقترب من تاريخ انتهاء الصلاحية.
داخل دليل مشروع wordpress_docker، افتح برنامجًا نصيًا يسمى ssl_renewer.sh باستخدام nano:
|
1 |
nano ssl_renewer.sh |
أضف الكود التالي إلى البرنامج النصي للتعامل مع التجديد التلقائي وإعادة تحميل تكوين Nginx. تذكر استبدال اسم المستخدم المميز باسم المستخدم الخاص بك غير الجذر (non-root):
|
1 2 3 4 5 6 7 8 |
#!/bin/bash COMPOSE="/usr/local/bin/docker-compose –ansi never" DOCKER="/usr/bin/docker" cd /home/hackins/wordpress_docker/ $COMPOSE run certbot renew --dry-run && $COMPOSE kill -s SIGHUP webserver $DOCKER system prune -af |
في هذا البرنامج النصي، نقوم بتعيين ملف docker-compose الثنائي إلى متغير يسمى COMPOSE. نقوم أيضًا بتضمين خيار –ansi never الذي يخبر البرنامج النصي بتشغيل أوامر docker-compose بدون أحرف ANSI control. نقوم أيضًا بتعيين ملف Docker الثنائي إلى متغير يسمى DOCKER.
ينتقل البرنامج النصي بعد ذلك إلى دليل مشروعنا wordpress_docker وينفذ الأوامر التالية:
docker-compose run: يقوم بتشغيل حاوية certbot ويتجاوز الأمر الذي قدمناه في تعريف خدمة certbot. بدلاً من تشغيل الأمر الفرعي certonly، فإنه يقوم بتشغيل الأمر الفرعي renew الذي سيجدد شهادات SSL/TLS من Let’s Encrypt إذا كانت على وشك الانتهاء.docker-compose kill: يرسل إشارة SIGHUP إلى حاويةwebserverلإعادة تحميل تكوينات Nginx. قد ترغب في مراجعة هذا البرنامج التعليمي من Docker حول كيفية استــخدام صورة Nginx Docker الـرسمية.docker system prune: يقوم هذا الأمر بإزالة جميع الحاويات والصور غير المستخدمة.
احفظ الملف وأغلقه عند الانتهاء من التعديل. ثم قم بتشغيل الأمر التالي لجعله قابلاً للتنفيذ:
|
1 |
chmod +x ssl_renewer.sh |
بمجرد جعله قابلاً للتنفيذ، افتح ملف crontab الخاص بالمستخدم الجذر (root) لتشغيل البرنامج النصي بشكل دوري بالفترات الزمنية التي سنحددها:
|
1 |
sudo crontab -e |
يطلب منك crontab اختيار المحرر المفضل لديك إذا كانت هذه هي المرة الأولى التي تستخدمه فيها:
اختر المحرر المفضل لديك واضغط على Enter لفتح الملف. في أسفل الملف، أضف السطر التالي:
|
1 |
*/5 * * * * /home/hackins/wordpress_docker/ssl_renewer.sh >> /var/log/cron_docker.log 2>&1 |
يؤدي هذا إلى تعيين الفاصل الزمني إلى خمس دقائق للسماح لنا باختبار ما إذا كان برنامج التجديد النصي الخاص بنا سيعمل أم لا. لقد قمنا أيضًا بتحديد ملف سجل سيحتوي على مخرجات المهمة: cron_docker.log.
انتظر لمدة خمس دقائق وتحقق من cron.log لمعرفة ما إذا كان البرنامج النصي ناجحًا في طلب التجديد:
|
1 |
tail -f /var/log/cron_docker.log |
يجب أن ترى شيئًا مشابهًا للقطة الشاشة أدناه إذا كانت الطلبات ناجحة:
الآن بعد أن قمنا باختبار وتأكيد أنه يعمل، يمكنك تعديل ملف crontab لتحديد تجديد يومي. على سبيل المثال، قد ترغب في تحديد تشغيل البرنامج النصي كل يوم في الساعة 6 مساءً. للقيام بذلك، قم بتعديل السطر الأخير من crontab ليبدو كالتالي:
|
1 |
0 18 * * * /home/hackins/wordpress_docker/ssl_renewer.sh >> /var/log/cron_docker.log 2>&1 |
بالإضافة إلى ذلك، تحتاج إلى إزالة علامة –dry-run من البرنامج النصي ssl_renewer.sh لضمان حدوث التجديد الفعلي عند تشغيله. يجب أن يبدو كالتالي:
|
1 2 3 4 5 6 7 8 |
#!/bin/bash COMPOSE="/usr/local/bin/docker-compose --ansi never" DOCKER="/usr/bin/docker" cd /home/hackins/wordpress_docker/ $COMPOSE run certbot renew && $COMPOSE kill -s SIGHUP webserver $DOCKER system prune -af |
بعد ذلك، احفظ الملف وأغلقه. بعد القيام بذلك، ستحافظ مهمة cron على صلاحية البرامج النصية الخاصة بك، عن طريق تجديدها قبل نهاية الـ 90 يومًا.
الخاتمة
إذا وصلت إلى هذا الحد في البرنامج التعليمي، فقد تعتبر نفسك خطوة أقرب إلى أن تصبح مهندس DevOps. لقد تمكنت من إنشاء برنامج نصي لتكوين Nginx، وأنشأت ملف docker-compose.yml، وحددت العديد من الخدمات اللازمة لتشغيل تطبيق WordPress باستخدام Docker و Docker Compose. لقد حصلت على شهادات SSL/TLS من Let’s Encrypt لضمان أمان خادم الويب الخاص بك. أخيرًا، قمت بإنشاء مهمة cron لضمان عدم انتهاء صلاحية الشهادات. عمل رائع!
إذا كنت تحاول التعمق أكثر في DevOps، فقم بإلقاء نظرة على المزيد من الموارد حول الحاويات من مدونتنا:
- التعرف على Kubernetes
- كيفية نشر تطبيق Node.js (Express.js) باستخدام Docker على Ubuntu 20.04
- نشر تطبيق PHP على مجموعة Kubernetes باستخدام Ubuntu 18.04.
- نشر Laravel و Nginx و MySQL باستخدام Docker Compose
حوسبة سعيدة!










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