مؤلف المادة ، الذي ننشر ترجمته اليوم ، هو مهندس DevOps. يقول أنه يجب أن يستخدم
عامل الميناء . على وجه الخصوص ، يتم استخدام نظام إدارة الحاويات هذا في المراحل المختلفة من دورة حياة تطبيقات Node.js. باستخدام Docker ، وهي تقنية شائعة جدًا مؤخرًا ، تتيح لك تحسين عملية التطوير والإخراج لمشاريع Node.js في الإنتاج.

نحن الآن ننشر
سلسلة من المقالات حول Docker ، مصممة لأولئك الذين يرغبون في تعلم هذه المنصة لاستخدامها في مجموعة متنوعة من المواقف. تركز نفس المادة بشكل أساسي على الاستخدام المهني لـ Docker في تطوير Node.js.
ما هو عامل ميناء؟
Docker هو برنامج مصمم لتنظيم المحاكاة الافتراضية على مستوى نظام التشغيل (حاويات). في قلب الحاويات هي الصور الطبقات. ببساطة ، Docker هي أداة تسمح لك بإنشاء ونشر وتشغيل التطبيقات باستخدام حاويات مستقلة عن نظام التشغيل الذي تعمل عليه. تتضمن الحاوية صورة لنظام التشغيل الأساسي اللازم لتشغيل التطبيق ، والمكتبة التي يعتمد عليها هذا التطبيق ، وهذا التطبيق نفسه. إذا كانت هناك عدة حاويات تعمل على نفس الكمبيوتر ، فإنهم يستخدمون موارد هذا الكمبيوتر معًا. يمكن لحاويات المرسى أن تحزم المشروعات التي تم إنشاؤها باستخدام مجموعة متنوعة من التقنيات. نحن مهتمون بالمشاريع القائمة على Node.js.
إنشاء مشروع Node.js
قبل حزم مشروع Node.js في حاوية Docker ، نحتاج إلى إنشاء هذا المشروع. دعونا نفعل ذلك. هنا هو ملف
package.json
لهذا المشروع:
{ "name": "node-app", "version": "1.0.0", "description": "The best way to manage your Node app using Docker", "main": "index.js", "scripts": { "start": "node index.js" }, "author": "Ankit Jain <ankitjain28may77@gmail.com>", "license": "ISC", "dependencies": { "express": "^4.16.4" } }
لتثبيت تبعيات المشروع ، قم بتشغيل الأمر
npm install
. في سياق هذا الأمر ، من بين أشياء أخرى ، سيتم إنشاء ملف
package-lock.json
. قم الآن بإنشاء ملف
index.js
، والذي سيحتوي على رمز المشروع:
const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('The best way to manage your Node app using Docker\n'); }); app.listen(3000); console.log('Running on http://localhost:3000');
كما ترون ، فقد وصفنا هنا خادمًا بسيطًا يعرض بعض النص استجابةً لطلباته.
إنشاء Dockerfile
الآن وبعد أن أصبح التطبيق جاهزًا ، دعنا نتحدث عن كيفية تعبئته في حاوية Docker. وهي ستكون حول الجزء الأكثر أهمية في أي مشروع قائم على Docker ، حول Dockerfile.
Dockerfile هو ملف نصي يحتوي على إرشادات لإنشاء صورة Docker لتطبيق ما. تصف الإرشادات الموجودة في هذا الملف ، إذا لم يتم الدخول في التفاصيل ، إنشاء طبقات لنظام الملفات متعدد المستويات ، والذي يحتوي على كل ما يحتاجه التطبيق للعمل. يمكن للنظام الأساسي Docker تخزين طبقات الصور في ذاكرة التخزين المؤقت ، والتي عند إعادة استخدام الطبقات الموجودة بالفعل في ذاكرة التخزين المؤقت ، تسرع عملية بناء الصور.
في البرمجة الموجهة للكائنات ، هناك شيء مثل الفصل. يتم استخدام الفئات لإنشاء كائنات. في Docker ، يمكن مقارنة الصور بالفئات ، ويمكن مقارنة الحاويات مع مثيلات الصور ، أي مع الكائنات. النظر في عملية إنشاء Dockerfile ، والتي سوف تساعدنا على معرفة ذلك.
إنشاء Dockerfile فارغة:
touch Dockerfile
نظرًا لأننا سنبني حاوية لتطبيق Node.js ، فإن أول شيء نحتاج إلى وضعه في الحاوية سيكون صورة العقدة الأساسية ، والتي يمكن العثور عليها على
Docker Hub . سوف نستخدم نسخة LTS من Node.js. نتيجة لذلك ، سيكون أول بيان من Dockerfile لدينا هو البيان التالي:
FROM node:8
بعد ذلك ، قم بإنشاء دليل للرمز الخاص بنا. في الوقت نفسه ، بفضل تعليمات
ARG
المستخدمة هنا ، يمكننا ، عند الضرورة ، تحديد اسم دليل التطبيق بخلاف
/app
أثناء تجميع الحاوية. يمكن العثور على تفاصيل حول هذا الدليل
هنا .
بما أننا نستخدم صورة Node ، فسيتم بالفعل تثبيت منصات Node.js و npm فيها. باستخدام ما هو موجود بالفعل في الصورة ، يمكنك تنظيم تثبيت تبعيات المشروع. باستخدام علامة
--production
(أو إذا
NODE_ENV
تعيين
NODE_ENV
البيئة
NODE_ENV
على
production
) لن تقوم npm بتثبيت الوحدات النمطية المدرجة في قسم
devDependencies
من ملف
devDependencies
.
نحن هنا نقوم بنسخ ملف
package*.json
إلى الصورة ، بدلاً من ، على سبيل المثال ، نسخ جميع ملفات المشروع. نقوم بذلك فقط لأن تعليمات Dockerfile
RUN
و
COPY
و
ADD
تنشئ طبقات صور إضافية ، حتى تتمكن من استخدام ميزات التخزين المؤقت لطبقات النظام الأساسي Docker. من خلال هذا النهج ، في المرة التالية التي نجمع فيها صورة مماثلة ، سيعرف Docker ما إذا كان من الممكن إعادة استخدام طبقات الصور الموجودة بالفعل في ذاكرة التخزين المؤقت ، وإذا كان الأمر كذلك ، فستستفيد مما هو موجود بالفعل ، بدلاً من إنشاء طبقات جديدة طبقات. يتيح لك ذلك توفير الوقت بشكل خطير عند تجميع الطبقات أثناء العمل في المشروعات الكبيرة ، والتي تتضمن العديد من وحدات npm.
الآن قم بنسخ ملفات المشروع إلى دليل العمل الحالي. هنا لن نستخدم تعليمات
إضافة ، ولكن تعليمات
نسخة . في الواقع ، في معظم الحالات ، يوصى بإعطاء الأفضلية لتعليمات
COPY
.
تحتوي تعليمات
ADD
، بالمقارنة مع
COPY
، على بعض الميزات ، والتي ، مع ذلك ، ليست مطلوبة دائمًا. على سبيل المثال ، نحن نتحدث عن خيارات لتفريغ أرشيفات .tar وتنزيل الملفات بواسطة عنوان URL.
حاويات قفص الاتهام هي بيئات معزولة. هذا يعني أنه عندما يتم تشغيل التطبيق في الحاوية ، فلن نتمكن من التفاعل معه مباشرة دون فتح المنفذ الذي يستمع إليه هذا التطبيق. لإبلاغ Docker بوجود تطبيق في حاوية معينة يستمع إلى منفذ معين ، يمكنك استخدام تعليمة
EXPOSE .
حتى الآن ، قمنا باستخدام Dockerfile ، بوصفنا الصورة التي سيحتويها التطبيق وكل ما يحتاجه لبدء التشغيل بنجاح. الآن أضف التعليمات إلى الملف الذي يسمح لك ببدء تشغيل التطبيق. هذا هو تعليم
CMD . يتيح لك تحديد أمر معين مع المعلمات التي سيتم تنفيذها عند بدء تشغيل الحاوية ، وإذا لزم الأمر ، يمكن تجاوزها بواسطة أدوات سطر الأوامر.
إليك ما سيبدو عليه Dockerfile النهائي:
FROM node:8
تجميع الصور
لقد أعددنا ملف Dockerfile يحتوي على إرشادات لبناء الصورة ، والتي سيتم على أساسها إنشاء حاوية مع تطبيق قيد التشغيل. قم بتجميع الصورة عن طريق تنفيذ أمر من النموذج التالي:
docker build --build-arg <build arguments> -t <user-name>/<image-name>:<tag-name> /path/to/Dockerfile
في حالتنا ، سيبدو كما يلي:
docker build --build-arg APP_DIR=var/app -t ankitjain28may/node-app:V1 .
يحتوي Dockerfile على عبارة
ARG
تصف الوسيطة
APP_DIR
. هنا نضع معناها. إذا لم يتم ذلك ، فسيأخذ القيمة التي تم تعيينها إليه في الملف ، أي
app
.
بعد تجميع الصورة ، تحقق مما إذا كان Docker يراها. للقيام بذلك ، قم بتشغيل الأمر التالي:
docker images
استجابة لهذا الأمر ، يجب أن يكون الإخراج التالي تقريبًا.
صور عامل الميناءإطلاق الصور
بعد قيامنا بتجميع صورة Docker ، يمكننا تشغيلها ، أي إنشاء مثيل لها ، يتم تمثيله بواسطة حاوية العمل. للقيام بذلك ، استخدم أمرًا من هذا النوع:
docker run -p <External-port:exposed-port> -d --name <name of the container> <user-name>/<image-name>:<tag-name>
في حالتنا ، سيبدو كما يلي:
docker run -p 8000:3000 -d --name node-app ankitjain28may/node-app:V1
سنطلب من النظام معلومات حول حاويات العمل باستخدام هذا الأمر:
docker ps
استجابة لهذا ، يجب على النظام إخراج شيء مثل التالي:
حاويات قفص الاتهامحتى الآن ، كل شيء يسير كما هو متوقع ، على الرغم من أننا لم نحاول بعد الوصول إلى التطبيق الذي يعمل في الحاوية. وهي حاوية لدينا ، المسمى
node-app
، تستمع على المنفذ
8000
. لمحاولة الوصول إليه ، يمكنك فتح متصفح والذهاب إليه في
localhost:8000
. بالإضافة إلى ذلك ، للتحقق من صحة الحاوية ، يمكنك استخدام الأمر التالي:
curl -i localhost:8000
إذا كانت الحاوية تعمل فعليًا ، فسيتم إرجاع شيء مثل الذي هو موضح في الشكل التالي استجابة لهذا الأمر.
التحقق من صحة الحاويةعلى أساس نفس الصورة ، على سبيل المثال ، على أساس الإنشاء حديثًا ، من الممكن إنشاء العديد من الحاويات. بالإضافة إلى ذلك ، يمكنك إرسال صورتنا إلى سجل Docker Hub ، والذي سيمكن المطورين الآخرين من تحميل صورنا وإطلاق الحاويات المناسبة في المنزل. هذا النهج يبسط العمل مع المشاريع.
توصيات
فيما يلي بعض الاقتراحات التي تستحق الدراسة من أجل زيادة قوة Docker وإنشاء صور مضغوطة قدر الإمكان.
▍1. قم دائمًا بإنشاء ملف .dockerignore
في مجلد المشروع الذي تخطط لوضعه في الحاوية ، ستحتاج دائمًا إلى إنشاء ملف
.dockerignore
. يسمح لك بتجاهل الملفات والمجلدات غير المطلوبة عند إنشاء الصورة. باستخدام هذا النهج ، يمكننا تقليل سياق البنية المزعوم ، والذي سيتيح لنا تجميع الصورة بسرعة وتقليل حجمها. يدعم هذا الملف قوالب أسماء الملفات ، يشبه هذا الملف ملف
.gitignore
. يوصى بإضافة أمر إلى
.dockerignore
بسبب تجاهل
/.git
للمجلد /
/.git
، لأن هذا المجلد يحتوي عادة على مواد كبيرة (خاصة أثناء تطوير المشروع) وإضافته إلى الصورة يؤدي إلى زيادة في حجمه. بالإضافة إلى ذلك ، فإن نسخ هذا المجلد إلى صورة لا معنى له.
▍2. استخدم عملية تجميع الصور متعددة المراحل
ضع في اعتبارك المثال عندما نجمع مشروعًا لمؤسسة معينة. يستخدم هذا المشروع العديد من حزم npm ، ويمكن لكل حزمة تثبيت حزم إضافية يعتمد عليها. يؤدي تنفيذ كل هذه العمليات إلى قضاء وقت إضافي في عملية تجميع الصورة (على الرغم من أن ذلك بفضل قدرات التخزين المؤقت لـ Docker ليس بالأمر الهين). والأسوأ من ذلك ، أن الصورة الناتجة التي تحتوي على تبعيات مشروع معين كبيرة جدًا. هنا ، إذا كنا نتحدث عن مشاريع الواجهة الأمامية ، فيمكننا أن نتذكر أن هذه المشاريع عادة ما تتم معالجتها باستخدام حزم مثل webpack ، والتي تجعل من الممكن بسهولة حزم كل ما يحتاجه التطبيق في عملية البيع. نتيجة لذلك ، ملفات حزمة npm لمثل هذا المشروع غير ضرورية. وهذا يعني أنه يمكننا التخلص من هذه الملفات بعد بناء المشروع باستخدام نفس webpack.
مسلحين بهذه الفكرة ، حاول القيام بذلك:
مثل هذا النهج ، لن يناسبنا. كما سبق وقلنا ، فإن تعليمات
RUN
و
ADD
و
COPY
تنشئ طبقات تم تخزينها مؤقتًا بواسطة Docker ، لذلك نحن بحاجة إلى إيجاد طريقة للتعامل مع تثبيت التبعيات وتجميع المشروع والإزالة اللاحقة للملفات غير الضرورية بأمر واحد. على سبيل المثال ، قد يبدو كالتالي:
في هذا المثال ، لا يوجد سوى عبارة
RUN
واحدة تقوم بتثبيت التبعيات وإنشاء المشروع وحذف مجلد
node_modules
. هذا يؤدي إلى حقيقة أن حجم الصورة لن يكون بحجم الصورة التي تحتوي على مجلد
node_modules
. نحن نستخدم الملفات من هذا المجلد فقط أثناء عملية إنشاء المشروع ، ثم نقوم بحذفه. صحيح ، هذا النهج سيء لأنه يتطلب الكثير من الوقت لتثبيت تبعيات npm. يمكنك التخلص من هذا العيب باستخدام تقنية تجميع الصور متعدد المراحل.
تخيل أننا نعمل على مشروع الواجهة الأمامية الذي يحتوي على العديد من التبعيات ، ونحن نستخدم webpack لبناء هذا المشروع. مع هذا النهج ، يمكننا ، من أجل تقليل حجم الصورة ، الاستفادة من قدرات Docker
لتجميع الصور متعدد المراحل .
FROM node:8 As build
من خلال هذا النهج ، تكون الصورة الناتجة أصغر بكثير من الصورة السابقة ، ونستخدم أيضًا
node:alpine
الصورة
node:alpine
، وهي نفسها صغيرة جدًا. وهنا مقارنة بين زوج من الصور ، يمكن من خلالها أن نرى أن صورة
node:alpine
أصغر بكثير من صورة
node:8
.
مقارنة الصور من مستودع العقدة.3. استخدام عامل التخزين المؤقت
حاول استخدام قدرات التخزين المؤقت لـ Docker لإنشاء صورك. لقد سبق أن
package*.json
بهذه الميزة عند العمل مع ملف تم الوصول إليه بواسطة
package*.json
الاسم
package*.json
. هذا يقلل من وقت بناء الصورة. ولكن هذه الفرصة لا ينبغي أن تستخدم بتهور.
لنفترض أننا وصفنا في Dockerfile تثبيت حزم في صورة تم إنشاؤها من صورة
Ubuntu:16.04
الأساسية
Ubuntu:16.04
:
FROM ubuntu:16.04 RUN apt-get update && apt-get install -y \ curl \ package-1 \ . .
عندما يقوم النظام بمعالجة هذا الملف ، إذا كان هناك الكثير من الحزم المثبتة ، فستستغرق عمليات التحديث والتثبيت الكثير من الوقت. لتحسين الموقف ، قررنا الاستفادة من قدرات التخزين المؤقت للطبقة في Docker وإعادة كتابة Dockerfile كما يلي:
FROM ubuntu:16.04 RUN apt-get update RUN apt-get install -y \ curl \ package-1 \ . .
الآن ، عند تجميع الصورة لأول مرة ، كل شيء يسير كما ينبغي ، لأن ذاكرة التخزين المؤقت لم تتشكل بعد. تخيل الآن أننا بحاجة إلى تثبيت حزمة أخرى ،
package-2
. للقيام بذلك ، نعيد كتابة الملف:
FROM ubuntu:16.04 RUN apt-get update RUN apt-get install -y \ curl \ package-1 \ package-2 \ . .
نتيجة لهذا الأمر ، لن يتم تثبيت
package-2
أو تحديثها. لماذا؟ الحقيقة هي أنه عند تنفيذ تعليمات
RUN apt-get update
، لا يرى Docker أي فرق بين هذه التعليمات والتعليم الذي تم تنفيذه مسبقًا ، ونتيجة لذلك ، فإنه يأخذ البيانات من ذاكرة التخزين المؤقت. وهذه البيانات قديمة بالفعل. عند معالجة عملية
RUN apt-get install
تعليمة
RUN apt-get install
يقوم النظام بتنفيذها ، لأنه لا يبدو كأنه تعليمة مماثلة في Dockerfile السابق ، ولكن أثناء التثبيت ، قد تحدث أخطاء أو سيتم تثبيت الإصدار القديم من الحزم. نتيجة لذلك ، اتضح أنه يجب تنفيذ أوامر
update
والتثبيت ضمن نفس تعليمات
RUN
، كما هو مذكور في المثال الأول. التخزين المؤقت ميزة رائعة ، لكن الاستخدام المتهور لهذه الميزة يمكن أن يؤدي إلى مشاكل.
▍4. تقليل عدد طبقات الصور
يوصى ، كلما كان ذلك ممكنًا ، بالسعي لتقليل عدد طبقات الصور ، نظرًا لأن كل طبقة هي نظام ملفات صورة Docker ، مما يعني أنه كلما كانت طبقات الصورة أصغر ، كلما كانت أصغر حجمًا. عند استخدام العملية متعددة المراحل لتجميع الصور ، يتم تحقيق انخفاض في عدد الطبقات في الصورة وانخفاض في حجم الصورة.
ملخص
في هذه المقالة ، نظرنا في عملية تعبئة تطبيقات Node.js في حاويات Docker والعمل مع هذه الحاويات. بالإضافة إلى ذلك ، قدمنا بعض التوصيات التي ، بالمناسبة ، يمكن استخدامها ليس فقط عند إنشاء حاويات لمشاريع Node.js.
أعزائي القراء! إذا كنت تستخدم Docker بشكل احترافي عند العمل مع مشاريع Node.js ، فيرجى مشاركة التوصيات حول الاستخدام الفعال لهذا النظام مع المبتدئين.
