مقدمة
Node.js هو بيئة تشغيل JavaScript أصبحت شائعة في السنوات الأخيرة لبناء تطبيقات جانب الخادم.
يوضح هذا البرنامج التعليمي كيفية نشر تطبيق Node.js على خادم سحابي عبر Docker وDocker Hub وDocker Compose.
المتطلبات الأساسية
- يفترض هذا البرنامج التعليمي أن Docker مُثبّت على نظامك المحلي. إذا لم يكن مُثبّتًا، يُمكنك العثور على تعليمات التثبيت في الوثائق الرسمية.
- ستحتاج أيضًا إلى خادم سحابي يعمل بتوزيعة لينكس، ويفضل أوبونتو 24.04. إذا كنت تستخدم توزيعة أخرى، فقد تحتاج إلى اتباع تعليمات محددة لتثبيت Docker على الخادم.
- تتطلب بعض الخطوات أيضًا حساب Docker Hub (مجاني) لتحميل صورة Docker للتطبيق.
- إذا لم تكن لديك أي خبرة سابقة في Docker، فلا بأس بذلك، فهذا البرنامج التعليمي أساسي للغاية ويشرح المفاهيم الأساسية وراء ما نقوم به.
- تحتاج إلى تطبيق Node.js الذي يمكنك نشره.
حول Docker
إذا كنت قد بدأت للتو في استخدام Docker، فإليك بعض المصطلحات التي تستحق المراجعة للتأكد من أننا على نفس الصفحة.
- الصور: في Docker، الصور هي "لقطات" أو قوالب لنظام الملفات وتحتوي على كل ما هو مطلوب لتشغيل التطبيق.
- الحاويات: هي نسخٌ فعليةٌ قيد التشغيل للتطبيق. تُنشأ بأخذ قالب (صورة) وتحويله إلى شيءٍ قابلٍ للتشغيل وله حالة.
- الطبقات هي العناصر التي تُكوّن صورة Docker. كل طبقة مبنية فوق طبقة أخرى، مما يتيح لك توفير ميزة تُسمى التخزين المؤقت للطبقات. هذا يعني أنه عند تغيير طبقة واحدة فقط في الصورة، لن تحتاج إلى إعادة بناء أو تحميل جميع الطبقات.
- السجلات هي المكان الذي تُحمّل فيه (تُرسل) الصور لإتاحتها للعالم أو لمن يملكون بيانات اعتماد الوصول. في هذا البرنامج التعليمي، سنستخدم Docker Hub، ولكن هناك أيضًا بدائل تُقدمها GCP وAWS وAzure وGitHub وغيرها.
الخطوة 1 - إنشاء ملف Dockerfile
قم بإنشاء ملف يسمى Dockerfile بالمحتوى التالي في الدليل الجذر لمشروع Node.js الخاص بك:
FROM node:20.17
ENV NODE_ENV=production
WORKDIR /app
COPY package*.json .
RUN npm ci
COPY . .
EXPOSE 8080
CMD [ "node", "src/index.js" ]ملف Dockerfile هو المكان الذي تُدخل فيه التعليمات التي تُمكّن Docker من بناء صورة. تُمثّل كل تعليمات إنشاء طبقة تُعدّل نظام ملفات الصورة.
في هذه الحالة، نبني صورتنا انطلاقًا من قالب، يُسمى أحيانًا الصورة الأساسية، وهو في هذه الحالة node:20.17. هذه صورة رسمية مقدمة من شركة Docker، ويمكنك الاطلاع على مزيد من المعلومات عنها هنا.
الخطوة التالية هي ضبط متغير بيئة NODE_ENV على وضع الإنتاج. الهدف الرئيسي هنا هو تجنب تثبيت حزم التطوير عند تشغيل تثبيت npm التالي، ولكنه قد يؤدي غالبًا إلى تحسينات أفضل في الوحدات النمطية التي قد تعتمد عليها.
باستخدام الأمر WORKDIR، نقوم بنقل الدليل الحالي إلى /app، والذي بدوره يصبح الدليل الذي يتم فيه تنفيذ التعليمات التالية.
سطر الحزمة COPY*.json. ينسخ ملفي package.json وpackage-lock.json إلى مجلد /app في نظام ملفات صور Docker. يُرجى ملاحظة أن النقطة الأخيرة ضرورية للإشارة إلى الدليل الحالي.
الآن نستخدم توجيه RUN لتثبيت تبعيات الإنتاج باستخدام أمر npm ci (ci تعني التثبيت النظيف وهو مصمم للاستخدام في البيئات الآلية).
تجدر الإشارة هنا إلى أننا كنا حتى الآن ننسخ ملفات package*.json فقط إلى ملف البناء بدلاً من مجلد المشروع بأكمله. يتيح لنا هذا الاستفادة من التخزين المؤقت لطبقات Docker، بحيث يُمكن استخدام الطبقات دون الحاجة إلى إعادة بناء إذا لم تتغير الحزم التابعة.
السطر التالي (COPY . .) يقوم بنسخ الملفات المتبقية في الصورة.
اختياريًا، يمكننا تحديد رغبتنا في عرض منفذ شبكة محدد من الحاوية ليتمكن تطبيق الويب من الوصول إليه. تجدر الإشارة إلى أن توجيه EXPOSE لا يعرض المنفذ فعليًا: فكما هو موضح في الوثائق، فهو "يعمل بمثابة وثيقة بين الشخص الذي ينشئ الصورة والشخص الذي يُشغّل الحاوية حول المنافذ المراد نشرها". .
أخيرًا، يُحدد التوجيه الأخير الأمر الذي يجب على Docker استخدامه لتشغيل التطبيق عند بدء تشغيل الحاوية. في هذه الحالة، نفترض أن نقطة دخول التطبيق هي ملف index.js.
يُنصح عادةً بإنشاء ملف باسم .dockerignore مع ملف Dockerfile. هذا يضمن عدم نسخ الملفات غير المفيدة من جهاز الكمبيوتر إلى النسخة عند تشغيل الأمر COPY.
.git
Dockerfile
node_modulesفي هذه الحالة، لا نريد أن تكون إصدارات التطوير من الدلائل مثل git أو node_modules متاحة في القالب الذي نبني.
الخطوة 2 – إنشاء الصورة
الآن بعد أن أصبح لدينا Dockerfile، يمكننا إخبار Docker باستخدامه لبناء صورة.
يبدو الأمر الأساسي للقيام بذلك مثل الأمر التالي ويجب تشغيله في مجلد المشروع الرئيسي:
docker build -t myproject .
إذا لم يكتمل بنجاح مع الخطأ "/bin/sh -c npm ci"، فاستبدل npm ci في Dockerfile بـ npm install وحاول مرة أخرى.
يُحدد الخيار -t اسم الصورة، وهو في هذه الحالة myproject. في نهاية السطر، عليك إخبار Docker بالبحث عن ملف Dockerfile في الدليل الحالي.
ملاحظة: في المرة الأولى التي تقوم فيها بتشغيل البناء، سيستغرق الأمر بعض الوقت لأن Docker يحتاج إلى تنزيل جميع طبقات الصورة الأساسية (في هذه الحالة Node.js 20.17).
نظرًا لأننا نخطط لتحميل هذه الصورة إلى سجل Docker Hub عبر الإنترنت (للوصول إليها من خادمنا)، فنحن بحاجة إلى تسمية الصورة باستخدام اتفاقية تسمية محددة.
لذا فإن الأمر أعلاه سيبدو مثل هذا:
docker build -t username/myproject:latest .
حيث اسم المستخدم هو اسم مستخدم Docker Hub الخاص بك، واسم العائلة هو وسم الصورة. يمكن للصورة أن تحتوي على عدة وسوم، لذا قد ترى أحيانًا سير عمل مشابهًا لما يلي:
docker build -t myproject .
docker tag myproject username/myproject:latest
docker tag myproject username/myproject:20240905تعمل هذه الأوامر على إنشاء صورة ثم وضع علامة عليها باستخدام العلامات latest و20240904 (تاريخ آخر تحديث لهذا البرنامج التعليمي).
لا يحذف Docker Hub الصور القديمة افتراضيًا، ما يسمح لك بالاحتفاظ بسجل لجميع الصور التي أرسلتها إلى السجل. الصورة التي تحمل العلامة الأحدث هي دائمًا الصورة الأحدث، بينما تُضاف إلى الصور الأقدم علامة التاريخ.
الخطوة 3 – اضغط على الصورة
الآن بعد أن حصلنا على الصورة، نحتاج إلى رفعها إلى السجل. أولًا، شغّل الأمر التالي للتأكد من مصادقة نسخة Docker الخاصة بك مع Docker Hub:
docker login
ثم قم بتشغيل docker push لتحميل الصورة مع كافة العلامات.
docker push username/myproject
إذا كان تطبيقك صغيرًا، فيجب أن يكتمل هذا الأمر بسرعة، لأنه يحتاج فقط إلى تحميل الطبقات المرتبطة بتطبيق Node.js وتبعيات JavaScript الخاصة به.
بمجرد حصولك على إصدار جديد من الصورة، ستحتاج إلى تشغيل أمر push مرة أخرى للتأكد من تحميلها إلى Docker Hub.
الخطوة 4 - تثبيت Docker على Ubuntu 24.04
الآن، يُمكننا الانتقال إلى تثبيت Docker وDocker Compose على الخادم. كما ذُكر في المتطلبات الأساسية، يُفترض هنا أن يكون لديك خادم Ubuntu 24.04 مُثبّتًا مُسبقًا.
أولاً وقبل كل شيء، يتطلب تثبيت Docker بعض تبعيات النظام والتي يمكن تثبيتها باستخدام الأوامر التالية:
sudo apt-get update
sudo apt-get install ca-certificates curlالآن قم بإضافة مفتاح Docker GPG الرسمي وقم بتكوين مستودع apt مخصص:
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/nullأخيرًا، قم بتحديث دليل apt مرة أخرى وقم بتثبيت Docker Community Edition:
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginيقوم الأمر أعلاه أيضًا بتثبيت Docker Compose، وهي أداة تعمل على تبسيط إدارة الحاويات ودورة حياتها بشكل كبير.
تتضمن الخطوة المفيدة الأخيرة إضافة مستخدم Ubuntu الحالي إلى مجموعة docker حتى نتمكن من تشغيل أوامر Docker مباشرة منه.
يمكن القيام بذلك بسهولة باستخدام الأمر التالي:
sudo gpasswd -a myuser docker
تأكد من أن كل شيء يسير على ما يرام عن طريق تشغيل الأوامر التالية:
docker --version
docker ps
docker compose versionإذا لم ترى أي أخطاء أو تحذيرات، فأنت على ما يرام.
الخطوة 5 - تشغيل الحاوية باستخدام Docker Compose
قم بإنشاء ملف يسمى docker-compose.yml بالمحتوى التالي على الخادم الخاص بك:
services:
myproject:
container_name: 'myproject'
image: 'username/myproject'
restart: unless-stoppedهذا ملف Docker Compose أساسي جدًا يُهيئ حاوية واحدة باسم myproject استنادًا إلى اسم المستخدم/الصورة myproject من Docker Hub. إذا لم تُحدد تسمية، فسيتم تعيينها افتراضيًا على التسمية الأخيرة، ولكن يمكنك أيضًا تعيين تسمية محددة إذا أردت:
services:
myproject:
container_name: 'myproject'
image: 'username/myproject:20240904'
restart: unless-stoppedأخيرًا، تشير سمة إعادة التشغيل إلى أنه يجب إعادة تشغيل الحاوية تلقائيًا في حالة الفشل ما لم يتم إيقافها يدويًا.
إذا قمت بتشغيل أمر Compose هذا الآن، فسيتم إلغاء تسجيل صورة Docker ونأمل أن يتم تشغيل تطبيقك:
docker compose -f docker-compose.yml up
يُنشئ هذا الأمر حاويةً ويُشغّلها. يلتقط Docker مُخرجات الحاوية ويُعرضها لك في وحدة التحكم. اضغط على CTRL + C (أو CMD + C) وانتظر بضع ثوانٍ حتى تتوقف الحاوية.
إذا سارت الأمور على ما يرام، فأنت الآن جاهز لتشغيل الحاوية كخادم افتراضي، بحيث تستمر في العمل في الخلفية حتى تتوقف. يمكن تحقيق ذلك بإضافة الخيار -d إلى الأمر:
docker compose -f docker-compose.yml up -dبوم، عقدة! (أوه، أعني ذلك)
تأكد من إلقاء نظرة سريعة على وثائق مرجع ملف Compose، حيث يمكنك العثور على ميزات مفيدة مثل ربط منافذ الشبكة بين الخادم والحاوية. إليك مثال سريع لربط المنفذ الخارجي 80 بالمنفذ الداخلي 8080:
services:
myproject:
container_name: 'myproject'
image: 'username/myproject'
restart: unless-stopped
ports:
- '80:8080'الخطوة 6 – تثبيت الإصدار الجديد
لنفترض أنك بحاجة إلى إصدار تغيير على تطبيقك. ما لم تكن عمليات البناء التلقائية مُفعّلة، ستحتاج إلى تكرار الخطوتين ٢ و٣ حتى تظهر نسخة جديدة في Docker Hub.
بعد ذلك، على الخادم الخاص بك، تحتاج إلى سحب الصورة الجديدة يدويًا، مثل هذا:
docker compose -f docker-compose.yml pull
وأعد تشغيل الحاوية بالصورة الجديدة:
docker compose -f docker-compose.yml up -d --force-recreate
نتيجة
رائع، لقد نجحت! كانت هذه مقدمة أساسية لنشر تطبيقات Node.js على Ubuntu 24.04 باستخدام Docker وDocker Hub وDocker Compose.
لقد رأينا كيفية كتابة Dockerfile بسيط، وكيفية بناء الصورة، ودفعها، ونشرها على الخادم.
هناك المزيد حول Docker مما يغطيه هذا البرنامج التعليمي، لذا تأكد من إلقاء نظرة على وثائق Docker وDocker Compose لمعرفة المزيد عن المفاهيم والميزات.









