
تتم كتابة هذا المنشور بناءً على طلب العمال الذين يسألون بشكل دوري عن "كيفية تشغيل تطبيق Illuminate / Symfony / MyOwn Psr7 في عامل ميناء." لا أشعر بإعطاء رابط إلى منشور مكتوب مسبقًا ، لأن وجهات نظري حول كيفية حل المشكلة قد تغيرت كثيرًا.
كل ما سيتم كتابته أدناه هو تجربة ذاتية ، والتي (كما هو الحال دائمًا) لا تدعي أنها تعتبر القرار الصحيح الوحيد ، ولكن قد تبدو بعض الأساليب والحلول مفيدة ومفيدة لك.
سوف أستخدم Laravel أيضًا كتطبيق ، لأنه مألوف بالنسبة لي وعلى نطاق واسع. من الممكن التكيف مع الأطر / المكونات الأخرى المستندة إلى PSR-7 ، ولكن هذه القصة لا تتعلق بذلك.
خطأ في التعامل
أود أن أبدأ بما تبين أنه "ليس أفضل الممارسات" في سياق المقال السابق :
- الحاجة إلى تغيير بنية الملفات في المستودع
- باستخدام FPM. إذا كنا نريد الأداء من تطبيقاتنا ، فربما يكون أحد أفضل الحلول حتى في مرحلة اختيار التكنولوجيا هو التخلي عنه لصالح شيء أسرع و "ملائم" لحقيقة أن الذاكرة قد تتسرب. RoadRunner بواسطة lachezis هنا كما لم يحدث من قبل
- صورة منفصلة مع المصدر والأصول. على الرغم من حقيقة استخدام هذا الأسلوب ، يمكننا إعادة استخدام نفس الصورة لإنشاء توجيه أكثر تعقيدًا للطلبات الواردة (nginx في المقدمة لإرجاع ثابت ، يتم تقديم طلبات الديناميات بواسطة حاوية أخرى يتم طرح وحدة التخزين فيها بنفس المصادر - من أجل تحجيم أفضل) - أثبت هذا المخطط أنه معقد إلى حد ما في تشغيل المنتج. والأكثر من ذلك ، أن RR نفسها تعمل على تقديم الإحصائيات بشكل مثالي ، وإذا كان هناك الكثير من الإحصائيات (أو يمكن للمورد تحميل وعرض المحتوى الذي أنشأه المستخدمون) - فنحن نأخذه إلى CDN (حزمة S3 + CloudFront + CloudFlare تعمل بشكل جيد) وننسى هذه المشكلة من حيث المبدأ
- مجمع CI. أصبحت هذه مشكلة حقيقية عندما بدأت فترة "بناء اللحوم" النشطة في مراحل التجميع والاختبار التلقائي. المتأنق الذي لم يدعم CI من قبل ، يصبح من الصعب للغاية إجراء تغييرات عليه دون خوف من كسر أي شيء.
الآن ، ومع معرفة ما هي المشاكل التي تحتاج إلى إصلاح ومع فهم كيفية القيام بذلك ، أقترح المضي قدما في القضاء عليها. لم تتغير مجموعة "أدوات المطوّرين" - إنها نفس docker-ce
، docker-compose
، و Makefile
القوي.
نتيجة لذلك ، نحصل على:
- حاوية مستقلة مع تطبيق دون الحاجة إلى تركيب وحدة تخزين إضافية
- مثال على استخدام git-hooks - سنضع التبعيات اللازمة بعد
git pull
تلقائيًا ونحظر دفع الرمز إذا فشلت الاختبارات (سيتم تخزين الخطافات تحت git ، بشكل طبيعي) - سوف RoadRunner التعامل مع طلبات HTTP (ق)
- سيظل المطورون قادرين على تنفيذ
dd(..)
dump(..)
للتصحيح ، في حين لن يحدث عطل في مستعرضهم - يمكن تشغيل الاختبارات مباشرة من PHPStorm IDE ، في حين سيتم تشغيلها في الحاوية مع التطبيق
- سيجمع CI الصور لنا عند نشر علامة إصدار تطبيق جديد
- دعونا نأخذ القاعدة الصارمة المتمثلة في الحفاظ على الملفات
CHANGELOG.md
و ENVIRONMENT.md
مقدمة مرئية لنهج جديد
بالنسبة إلى العرض التوضيحي المرئي ، سأقسم العملية بأكملها إلى عدة مراحل ، حيث سيتم إجراء التغييرات داخلها على أنها MR منفصلة (بعد الدمج ، ستبقى جميع البرنش في أماكنهم ؛ والإشارات إلى MR في عناوين "الخطوات"). تتمثل نقطة الانطلاق في الهيكل العظمي Laravel لتطبيق تم إنشاؤه باستخدام composer create-project laravel/laravel
:
$ docker run \ --rm -i \ -v "$(pwd):/src" \ -u "$(id -u):$(id -g)" \ composer composer create-project --prefer-dist laravel/laravel \ /src/laravel-in-docker-with-rr "5.8.*"
الخطوة الأولى هي تعليم التطبيق لتشغيله في الحاوية. للقيام بذلك ، نحتاج إلى Dockerfile
، Dockerfile
docker-compose.yml
Dockerfile
للحصول على وصف "كيفية رفع وربط الحاويات" ، و Makefile
أجل تقليل عملية مبسطة بالفعل إلى أمر واحد أو أمرين.
Dockerfile
الصورة الأساسية التي php:XXX-alpine
هي الأسهل وتحتوي على ما تحتاج إلى تشغيله. علاوة على ذلك ، يتم تقليل جميع التحديثات اللاحقة للمترجم الشفهي إلى مجرد تغيير القيمة في هذا السطر (أصبح تحديث PHP أسهل من أي وقت مضى).
يتم تسليم الملحن والملف الثنائي RoadRunner إلى الحاوية باستخدام متعدد المراحل و COPY --from=...
- هذا ملائم للغاية ، وجميع القيم المرتبطة بالإصدارات ليست "مبعثرة" ، ولكنها في بداية الملف. هذا يعمل بسرعة ، ودون الاعتماد على curl
/ git clone
/ make build
. يتم دعم صور 512k / roadrunner من قبلي ، إذا كنت تريد - يمكنك تجميع الملف الثنائي بنفسك.
حدثت قصة مثيرة للاهتمام مع متغير البيئة PS1
(المسؤول عن المطالبة في shell) - اتضح أنه يمكنك استخدام الرموز التعبيرية فيه ، وكل شيء يعمل محليًا ، ولكن إذا حاولت بدء الصورة مع متغير يحتوي على رموز تعبيرية ، على سبيل المثال ، مزرعة ، فسوف تتعطل (في سرب كل شيء يعمل دون مشاكل).
في Dockerfile
أبدأ في إنشاء شهادة SSL موقعة ذاتيًا لاستخدامها لطلبات HTTPS الواردة. بطبيعة الحال - لا شيء يمنع استخدام شهادة "طبيعية".
أود أيضًا أن أقول عن:
COPY ./composer.* /app/ RUN set -xe \ && composer install --no-interaction --no-ansi --no-suggest --prefer-dist \ --no-autoloader --no-scripts \ && composer install --no-dev --no-interaction --no-ansi --no-suggest \ --prefer-dist --no-autoloader --no-scripts
المعنى هنا هو التالي - يتم تسليم ملفات composer.json
و composer.json
في طبقة منفصلة للصورة ، وبعد ذلك يتم تثبيت جميع التبعيات الموصوفة فيها. يتم ذلك حتى يتم إنشاء نسخ من التبعيات المثبتة وإصداراتها ، أثناء عمليات --cache-from
اللاحقة للصورة باستخدام --cache-from
ذاكرة التخزين المؤقت ، ثم لم composer install
تنفيذ composer install
، مع أخذ هذه الطبقة من ذاكرة التخزين المؤقت ، وبالتالي توفير وقت البناء وحركة المرور (شكرًا على الفكرة jetexe ).
يتم تنفيذ composer install
مرتين (المرة الثانية مع --no-dev
) "لتسخين" ذاكرة التخزين المؤقت تبعيات dev ، بحيث عندما نضع كل التبعيات على CI لتشغيل الاختبارات ، يتم وضعها من ذاكرة التخزين المؤقت للملحن ، الموجودة بالفعل في الصورة ، وليس امتدت من المجرات البعيدة.
باستخدام تعليمة RUN
الأخيرة ، نعرض إصدارات البرنامج المثبت وتكوين وحدات PHP لكل من السجل في سجلات الإنشاء وللتأكد من "أنه موجود على الأقل ويبدأ بطريقة ما."
يمكنني أيضًا استخدام Entrypoint ، لأنني قبل بدء التطبيق في مكان ما في المجموعة ، أريد حقًا التحقق من توفر الخدمات التابعة - DB ، redis ، الأرنب وغيرها.
رود رنر
لدمج RoadRunner مع تطبيق Laravel ، تمت كتابة حزمة تقلل كل التكامل إلى بضعة أوامر في shell (عن طريق docker-compose run app sh
docker-compose):
$ composer require avto-dev/roadrunner-laravel "^2.0" $ ./artisan vendor:publish --provider='AvtoDev\RoadRunnerLaravel\ServiceProvider' --tag=rr-config
أضف APP_FORCE_HTTPS=true
إلى ملف ./docker/docker-compose.env
، وحدد المسار إلى شهادة SSL في الحاوية في .rr*.yaml
.
من أجل أن تكون قادرًا على استخدام dump(..)
و dd(..)
وسيعمل كل شيء ، هناك حزمة أخرى - avto-dev/stacked-dumper-laravel
. كل ما هو مطلوب هو إضافة pefix إلى هؤلاء المساعدين ، أي \dev\dd(..)
و \dev\dump(..)
على التوالي. بدون هذا ، ستلاحظ وجود خطأ في النموذج:
worker error: invalid data found in the buffer (possible echo)
بعد كل عمليات التلاعب ، قم docker-compose up -d
فويلا و:

ركزت قاعدة بيانات PostgeSQL وعمال redis و RoadRunner بنجاح في حاويات.
كما كتبت في وقت سابق ، Makefile هو عنصر الاستخفاف جدا. الأهداف التابعة ، السكر النحوي الخاص بك ، فرصة بنسبة 99 ٪ أنه يقف بالفعل على آلة تطوير Linux / mac ، الإكمال التلقائي "خارج الصندوق" - قائمة صغيرة من مزاياها.
إضافة إلى مشروعنا والقيام دون المعلمات ، يمكننا أن نلاحظ:

لتشغيل اختبارات الوحدة ، يمكننا إما make test
، أو الحصول على غلاف داخل الحاوية مع التطبيق ( make shell
) ، أو تشغيل composer phpunit
. للحصول على تقرير التغطية ، قم فقط بإجراء make test-cover
، وقبل تشغيل الاختبارات ، سيتم تسليم xdebug بتبعياته إلى الحاوية وسيتم تشغيل الاختبارات (نظرًا لأن هذا الإجراء لا يتم تنفيذه في كثير من الأحيان وليس بواسطة CI - يبدو أن هذا الحل أفضل من الحفاظ على صورة منفصلة مع الكل ديف المستحضرات).
السنانير بوابة
الخطافات في حالتنا ستؤدي أدوارًا مهمة - عدم السماح بدفع الكود إلى الأصل الذي لم تنجح اختباراته ؛ ووضع كل التبعيات اللازمة تلقائيًا إذا تبين ، بعد سحب التغييرات على جهازك ، أنه قد تم تغيير composer.lock
. في Makefile
، يوجد هدف منفصل لهذا:
cwd = $(shell pwd) git-hooks: ## Install (reinstall) git hooks (required after repository cloning) -rm -f "$(cwd)/.git/hooks/pre-push" "$(cwd)/.git/hooks/pre-commit" "$(cwd)/.git/hooks/post-merge" ln -s "$(cwd)/.gitlab/git-hooks/pre-push.sh" "$(cwd)/.git/hooks/pre-push" ln -s "$(cwd)/.gitlab/git-hooks/pre-commit.sh" "$(cwd)/.git/hooks/pre-commit" ln -s "$(cwd)/.gitlab/git-hooks/post-merge.sh" "$(cwd)/.git/hooks/post-merge"
القيام make git-hooks
ببساطة يسلب السنانير الموجودة ويضعها في دليل .gitlab/git-hooks
في مكانها. يمكن الاطلاع على مصدرها على هذا الرابط .
تشغيل الاختبارات من PhpStorm
على الرغم من أن الأمر بسيط ومريح للغاية - فقد استخدمته لفترة طويلة ./vendor/bin/phpunit --group=foo
بدلاً من الضغط على مفتاح ./vendor/bin/phpunit --group=foo
مباشرةً أثناء كتابة اختبار أو رمز مرتبط به.
انقر فوق File > Settings > Languages & Frameworks > PHP > CLI interpreter > [...] > [+] > From Docker, Vargant, VM, Remote
. حدد Docker يؤلف ، واسم خدمة التطبيق .

والخطوة الثانية هي إخبار phpunit باستخدام المترجم من الحاوية: File > Settings > Test frameworks > [+] > PHPUnit by remote interpreter
وحدد المترجم البعيد الذي تم إنشاؤه مسبقًا. في /app/vendor/autoload.php
Path to script
، حدد /app/vendor/autoload.php
، وفي Path mappings
نحدد الدليل الجذر للمشروع كما هو مثبت في /app
.

والآن يمكننا إجراء اختبارات مباشرة من IDE باستخدام المترجم داخل الصورة مع التطبيق ، والضغط (افتراضيًا ، Linux) Ctrl + Shift + F10.
كل ما تبقى بالنسبة لنا هو أتمتة عملية إجراء الاختبارات وتجميع الصورة. للقيام بذلك ، قم بإنشاء .gitlab-ci.yml
في الدليل الجذر للتطبيق ، مع ملء المحتويات التالية . الفكرة الرئيسية لهذا التكوين هي أن تكون بسيطة قدر الإمكان ، ولكن لا تفقد الوظيفة في نفس الوقت.
يتم تجميع الصورة في كل وجبة غداء ، عند كل التزام. باستخدام - --cache-from
تجميع الصورة عند إعادة الالتزام سريع للغاية. تعود الحاجة إلى إعادة البناء إلى حقيقة أنه في كل وجبة فطور ، لدينا صورة مع التغييرات التي تم إجراؤها كجزء من هذا الغداء ، ونتيجة لذلك ، لا شيء يمنعنا من طرحها على سرب / k8s / إلخ من أجل التأكد من "العيش" أن كل شيء يعمل ، ويعمل كما يجب حتى قبل الدمج مع الضوء الرئيسي.
بعد التجميع ، نجري اختبارات الوحدة ونتحقق من بدء تشغيل التطبيق في الحاوية ، وإرسال طلبات الضفيرة إلى نقطة نهاية الفحص الصحي (هذا الإجراء اختياري ، لكن هذا الاختبار ساعدني كثيرًا عدة مرات).
بالنسبة إلى "إصدار الإصدار" - ما عليك سوى نشر علامة من النموذج vX.XX
(إذا كنت لا تزال vX.XX
الدلالي - سيكون رائعًا للغاية) - تجمع CI الصورة ، vX.XX
الإجراءات التي تحددها عند deploy to somewhere
.
لا تنسَ في إعدادات المشروع (إن أمكن) قصر القدرة على نشر العلامات فقط على الأشخاص المسموح لهم "بإصدار إصدارات".
CHANGELOG.md
و CHANGELOG.md
قبل قبول MR واحد أو آخر ، يجب على المفتش ، دون إخفاق ، التحقق من ملفات CHANGELOG.md
و ENVIRONMENT.md
CHANGELOG.md
ENVIRONMENT.md
. إذا كان الأول أكثر وضوحا ، فإن الثانية النسبية سأقدم شرحا. يستخدم هذا الملف لوصف جميع متغيرات البيئة التي يستجيب لها الحاوية مع التطبيق. أي إذا قام المطور بإضافة أو إزالة الدعم لمتغير بيئة أو آخر ، يجب أن ينعكس هذا في هذا الملف. وفي الوقت الذي يطرح فيه السؤال "نحن بحاجة ماسة لإعادة تعريف هذا وذاك" - لا أحد يبدأ بشكل محموم في الخوض في الوثائق أو أكواد المصدر - لكنه يبحث في ملف واحد. مريح جدا
استنتاج
في هذه المقالة ، قمنا بفحص العملية غير المؤلمة إلى حد ما لنقل تطوير التطبيق والإطلاق إلى بيئة Docker ، RoadRunner المدمجة ، واستخدام برنامج نصي بسيط CI يقوم تلقائيًا بتجميع واختبار الصورة من خلال تطبيقنا.
بعد استنساخ المستودع ، يتعين على المطورين make git-hooks && make install && make up
والبدء في كتابة التعليمات البرمجية المفيدة. الرفاق * ops-am - التقط الصورة بالعلامة المرغوبة وقم بلفها على مجموعاتهم.
بطبيعة الحال - هذا المخطط مبسط أيضًا ، وفي المشروعات "القتالية" سأختتم أكثر من ذلك بكثير ، لكن إذا كان النهج الموصوف في المقالة يساعد شخصًا ما ، فسنعلم أنني أهدرت وقتي.