ما هو Docker؟ دليل شامل للمبتدئين حول استخدام حاويات Docker

دقائق القراءة: 15

مقدمة إلى عالم Docker: لماذا أصبح لا غنى عنه للمطورين؟

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

لمحة تاريخية عن الحاويات: من الجذور إلى الثورة

Docker هو بيئة تشغيل للحاويات (container runtime). يعتقد الكثيرون أن Docker كان الأول من نوعه، لكن هذا ليس صحيحًا – فقد وُجدت حاويات Linux منذ سبعينيات القرن الماضي. تكمن أهمية Docker لمجتمع التطوير ومجتمع الحاويات في أنه جعل استخدام الحاويات سهلاً للغاية، لدرجة أن الجميع بدأ في استخدامها.

ما هي الحاويات؟

الحاويات، أو حاويات Linux، هي تقنية تسمح لنا بعزل عمليات معينة من نواة نظام التشغيل (kernel processes) وخداعها لتعتقد أنها الوحيدة التي تعمل في جهاز كمبيوتر جديد تمامًا. على عكس الآلات الافتراضية (Virtual Machines - VMs)، يمكن للحاوية مشاركة نواة نظام التشغيل بينما يتم تحميل الثنائيات والمكتبات (binaries/libraries) المختلفة الخاصة بها فقط. بعبارة أخرى، لا تحتاج إلى تثبيت نظام تشغيل كامل ومختلف (يُسمى guest OS) داخل نظام التشغيل المضيف (host OS) الخاص بك. يمكنك تشغيل عدة حاويات ضمن نظام تشغيل واحد دون الحاجة إلى تثبيت أنظمة تشغيل ضيفة متعددة.

الفرق بين الآلات الافتراضية وحاويات Docker

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

بداية الحاويات: من chroot إلى LXC

يبدأ تاريخ الحاويات في عام 1979 مع إصدار Unix v7. في ذلك الوقت، لم أكن قد ولدت بعد، وكان والدي يبلغ من العمر 15 عامًا. هل كانت الحاويات موجودة بالفعل في عام 1979؟ لا! في عام 1979، قدم إصدار Unix السابع استدعاء نظام (system call) يُسمى chroot، والذي كان البداية الحقيقية لما نعرفه اليوم باسم الافتراضية للعمليات (process virtualization). سمح استدعاء chroot للنواة بتغيير الدليل الجذر الظاهري لعملية ما وعملياتها الفرعية. باختصار، تعتقد العملية أنها تعمل بمفردها في الجهاز، لأن نظام ملفاتها معزول عن جميع العمليات الأخرى. تم تقديم نفس استدعاء النظام هذا في BSD عام 1982. ولكن لم يكن هناك تطبيق واسع النطاق له إلا بعد عقدين من الزمن.

في عام 2000، كان مزود استضافة يبحث عن طرق أفضل لإدارة مواقع الويب لعملائه، نظرًا لأنها كانت جميعها مثبتة على نفس الجهاز وتتنافس على نفس الموارد. كان هذا الحل يُسمى jails، وكان أحد المحاولات الحقيقية الأولى لعزل الأشياء على مستوى العملية. سمحت jails لأي مستخدمي FreeBSD بتقسيم النظام إلى عدة أنظمة مستقلة وأصغر (تُسمى jails). يمكن لكل jail أن يكون له تكوينه الخاص لعنوان IP وتكوين النظام. كانت jails هي الحل الأول لتوسيع استخدامات chroot للسماح ليس فقط بالعزل على مستوى نظام الملفات، ولكن أيضًا بافتراضية المستخدمين والشبكة والأنظمة الفرعية وما إلى ذلك.

في عام 2008، تم إطلاق LXC (اختصار لـ Linux Containers). كان في ذلك الوقت أول وأكمل تطبيق لنظام إدارة الحاويات. استخدم مجموعات التحكم (control groups) ومساحات الأسماء (namespaces) والكثير مما تم بناؤه حتى ذلك الحين. كان التقدم الأكبر هو أنه كان يُستخدم مباشرة من نواة Unix، ولم يتطلب أي تعديلات.

Docker: تبسيط الحاويات وجعلها في متناول الجميع

أخيرًا، في عام 2010، أنشأ سولومون هايكس وسيباستيان بال Docker خلال مجموعة حاضنة الشركات الناشئة Y Combinator. في عام 2011، تم إطلاق المنصة. في الأصل، بدأ هايكس مشروع Docker في فرنسا كجزء من مشروع داخلي داخل dotCloud، وهي شركة PaaS أُغلقت في عام 2016. لم يضف Docker الكثير إلى بيئات تشغيل الحاويات في ذلك الوقت – كانت المساهمة الأكبر من Docker في نظام الحاويات البيئي هي الوعي. لقد أدت واجهة سطر الأوامر (CLI) ومفاهيمه سهلة الاستخدام إلى إضفاء الطابع الديمقراطي على استخدام الحاويات للمطورين العاديين، وليس فقط لشركات القرصنة العميقة التي كانت تحتاج إلى الحاويات لسبب ما.

بعد عام 2013، بدأت العديد من الشركات في اعتماد Docker كبيئة تشغيل حاويات افتراضية لأنه وحد استخدام الحاويات في جميع أنحاء العالم. في عام 2013، أعلنت Red Hat عن تعاون مع Docker، وفي عام 2014، حان الوقت لـ Microsoft وAWS وStratoscale وIBM. في عام 2016، تم الإعلان عن الإصدار الأول من Docker لنظام تشغيل مختلف عن Linux. أصدرت Windocks منفذًا لمشروع OSS الخاص بـ Docker مصممًا للعمل على Windows. وبحلول نهاية نفس العام، أعلنت Microsoft أن Docker أصبح مدعومًا بشكل أصلي على Windows من خلال Hyper-V. في عام 2019، أعلنت Microsoft عن WSL2، مما أتاح لـ Docker العمل على Windows دون الحاجة إلى آلة افتراضية على Hyper-V. أصبح Docker الآن متعدد المنصات بشكل أصلي بينما لا يزال يستفيد من نهج حاويات Linux.

أخيرًا، في عام 2020، أصبح Docker الخيار العالمي للحاويات. لم يحدث هذا بالضرورة لأنه أفضل من غيره، ولكن لأنه يوحد جميع التطبيقات تحت منصة واحدة سهلة الاستخدام مع واجهة سطر أوامر (CLI) وخدمة خلفية (Daemon). ويقوم بكل هذا باستخدام مفاهيم بسيطة سنستكشفها في الأقسام التالية.

كيف يعمل Docker؟

يقوم Docker بتجميع تطبيق وجميع تبعياته في حاوية افتراضية يمكن تشغيلها على أي خادم Linux. لهذا السبب نسميها حاويات؛ لأنها تحتوي على جميع التبعيات الضرورية في قطعة واحدة من البرمجيات. يتكون Docker من العناصر التالية:

  • Daemon: وهي خدمة تعمل في الخلفية تُستخدم لبناء وتشغيل وإدارة الحاويات.
  • واجهة برمجة تطبيقات (API) عالية المستوى: تسمح للمستخدم بالتواصل مع الـ Daemon.
  • واجهة سطر الأوامر (CLI): وهي الواجهة التي نستخدمها لجعل كل هذا متاحًا.

حاويات Docker: العزل والكفاءة

الحاويات هي تجريدات لطبقة التطبيق. تقوم بتجميع جميع التعليمات البرمجية والمكتبات والتبعيات معًا. هذا يجعل من الممكن تشغيل حاويات متعددة في نفس المضيف (host)، بحيث يمكنك استخدام موارد هذا المضيف بكفاءة أكبر. تعمل كل حاوية كعملية معزولة في مساحة المستخدم (user space) وتشغل مساحة أقل من الآلات الافتراضية العادية بسبب بنيتها الطبقية. تُسمى هذه الطبقات الصور الوسيطة (intermediate images)، ويتم إنشاء هذه الصور في كل مرة تقوم فيها بتشغيل أمر جديد في ملف Dockerfile. على سبيل المثال، إذا كان لديك Dockerfile يشبه هذا:

 FROM node:stable
 COPY . /usr/src/app
 WORKDIR /usr/src/app
 RUN npm install grpc
 RUN npm install
 ENTRYPOINT [ "npm" , "start" ]

عند كل أمر مثل COPY أو RUN، ستقوم بإنشاء طبقة أخرى فوق صورة الحاوية الخاصة بك. هذا يسمح لـ Docker بتقسيم وفصل كل أمر إلى جزء منفصل. لذلك إذا استخدمت صورة node:stable هذه مرة أخرى في النهاية، فلن تحتاج إلى سحب جميع طبقاتها، لأنك قمت بالفعل بتثبيت هذه الصورة. أيضًا، يتم تجزئة جميع الطبقات (hashed)، مما يعني أن Docker يمكنه تخزين هذه الطبقات مؤقتًا وتحسين أوقات البناء للطبقات التي لم تتغير عبر عمليات البناء. لن تحتاج إلى إعادة بناء وإعادة نسخ جميع الملفات إذا لم تتغير خطوة COPY، مما يقلل بشكل كبير من الوقت المستغرق في عمليات البناء.

في نهاية عملية البناء، يقوم Docker بإنشاء طبقة فارغة جديدة فوق جميع الطبقات تُسمى الطبقة القابلة للكتابة الرقيقة (thin writable layer). هذه الطبقة هي التي تصل إليها عند استخدام الأمر docker exec -it <container> <command>. بهذه الطريقة يمكنك إجراء تغييرات تفاعلية في الصورة وتثبيت هذه التغييرات باستخدام docker commit، تمامًا كما تفعل مع ملف يتم تتبعه بواسطة Git. هذه البنية الطبقية المتباينة بالتجزئة ممكنة بفضل نظام الملفات AuFS. هذا نظام ملفات طبقي يسمح بتكديس الملفات والدلائل كطبقات فوق بعضها البعض. يطرح AuFS بعض المشاكل عند التعامل مع DnD (Docker in Docker)، ولكن هذا موضوع لمقال آخر!

الطبقات في Docker يمكن مقارنة التجزئة بين الإصدارات لتوفير وقت البناء

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

شرح طبقات Docker وكيفية تجميعها لتشكيل صورة كاملة (المصدر: Packt)

لماذا تعتبر حاويات Docker رائعة؟

ربما سمعت العبارة الشهيرة إنها تعمل على جهازي (It works on my machine). حسنًا، لماذا لا نعطي هذا الجهاز للعميل؟ هذا بالضبط المشكلة التي يحلها Docker والحاويات بشكل عام. حاوية Docker هي مجموعة مجمعة من جميع مكتبات التطبيق وتبعياته، مُعدة مسبقًا وجاهزة للتنفيذ. لقد هاجرت العديد من الشركات من الآلات الافتراضية (VMs) إلى الحاويات ليس فقط لأنها أخف بكثير وأسرع في التشغيل، ولكن أيضًا لأنها سهلة الصيانة للغاية. يمكن إصدار حاوية واحدة باستخدام Dockerfile الخاص بها (سنتطرق إلى الصور في القسم التالي)، مما يجعل من السهل جدًا على مطور واحد (أو حتى فريق صغير من المطورين) تشغيل وصيانة نظام بيئي كامل من الحاويات. من ناحية أخرى، ستحتاج إلى شخص متخصص في البنية التحتية لمجرد تشغيل وصيانة الآلات الافتراضية.

مقارنة بين مركز البيانات الذي يستخدم الآلات الافتراضية ومركز البيانات الذي يستخدم الحاويات (المصدر: Docker)

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

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

لا يزال مرتبطًا بالتوفير، يمكن لآلة افتراضية متوسطة الحجم تشغيل حوالي 3 إلى 8 حاويات. يعتمد ذلك على عدد الموارد التي تستخدمها حاوياتك ومقدار نظام التشغيل الأساسي الذي تحتاجه للتشغيل قبل تشغيل التطبيق بأكمله. تسمح لك بعض اللغات، مثل Go، ببناء صورة تحتوي فقط على الثنائي المترجم (compiled binary) ولا شيء آخر. هذا يعني أن حاوية Docker ستحتاج إلى تحميل أقل بكثير، وبالتالي ستستخدم موارد أقل. بهذه الطريقة يمكنك تشغيل المزيد من الحاويات لكل آلة افتراضية واستخدام أجهزتك بكفاءة أكبر.

نظرًا لأن الحاويات مصممة لتكون مؤقتة (ephemeral)، فهذا يعني أن جميع البيانات داخلها تُفقد عند حذف الحاوية. هذا أمر رائع، لأنه يمكننا استخدام الحاويات للمهام القابلة للانفجار (burstable tasks) مثل التكامل المستمر (CI). لقد أدى استخدام الحاويات إلى مستوى جديد تمامًا من التطورات في DevOps. يمكنك الآن ببساطة تشغيل الكثير من الحاويات، كل واحدة تقوم بخطوة صغيرة واحدة من مسار النشر الخاص بك، ثم قتلها دون القلق إذا تركت شيئًا وراءك. الطبيعة عديمة الحالة (stateless) للحاويات تجعلها الأداة المثالية لأعباء العمل السريعة. الآن بعد أن رأينا مدى روعة الحاويات، دعنا نفهم كيف يمكننا بناء واحدة منها!

ما هي صور Docker؟

صور Docker هي تعليمات مكتوبة في ملف خاص يُسمى Dockerfile. لها بناء جملة خاص بها وتحدد الخطوات التي سيتخذها Docker لبناء حاويتك. نظرًا لأن الحاويات ليست سوى طبقات فوق طبقات من التغييرات، فإن كل أمر جديد تقوم بإنشائه في صورة Docker سيؤدي إلى إنشاء طبقة جديدة في الحاوية. الطبقة الأخيرة هي ما نسميه الطبقة القابلة للكتابة الرقيقة (thin writable layer)، وهي طبقة فارغة يمكن للمستخدم تغييرها وتثبيت التغييرات باستخدام الأمر docker commit.

هذا مثال لصورة بسيطة لتطبيق Node.js:

 FROM node:stable
 COPY . /usr/src/app/
 RUN npm install && npm run build
 EXPOSE 3000
 ENTRYPOINT [ "npm" , "start" ]

في هذا المثال البسيط، نقوم بإنشاء صورة جديدة. تستند جميع الصور إلى صورة موجودة، أو صورة من الصفر (scratch image) (والتي أشرحها في مقالات مدونتي باللغة البرتغالية، هنا وهنا وهنا). يتم تنزيل هذه الصور من سجل الحاويات (Container Registry)، وهو مستودع لتخزين صور الحاويات. الأكثر شيوعًا هو Docker Hub، ولكن يمكنك أيضًا إنشاء سجل خاص باستخدام حلول سحابية مثل Azure Container Registry.

عند تشغيل docker build . في نفس الدليل الذي يحتوي على Dockerfile، سيبدأ Docker daemon في بناء الصورة وتجميعها حتى تتمكن من استخدامها. بعد ذلك، يمكنك تشغيل docker run <image-name> لبدء حاوية جديدة. لاحظ أننا نكشف عن منافذ معينة في Dockerfile. يسمح لنا Docker بفصل الشبكات داخل نظام التشغيل الخاص بنا، مما يعني أنه يمكنك تعيين المنافذ من جهاز الكمبيوتر الخاص بك إلى الحاوية والعكس صحيح. أيضًا، يمكنك تنفيذ الأوامر داخل الحاويات باستخدام docker exec. دعنا نضع هذه المعرفة موضع التنفيذ.

كيفية نشر تطبيقك المجهز بـ Docker (Dockerized Application)

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

أولاً، ابدأ مشروعًا جديدًا في دليل من اختيارك، وقم بتشغيل npm init -y لإنشاء ملف package.json جديد. الآن دعنا ننشئ دليلًا آخر يُسمى src. في هذا الدليل، سنقوم بإنشاء ملف جديد يُسمى server.js. ضع المحتوى التالي داخل ملف server.js:

const http = require('http');

const hostname = '0.0.0.0'; // Listen on all network interfaces
const port = 8089;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello from Docker!\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

الآن، في ملف package.json الخاص بك، قم بتغيير المفتاح main إلى src/server.js. أيضًا، احذف السكريبت test الذي تم إنشاؤه واستبدله بـ "start": "node src/server.js". يجب أن يبدو ملفك كما يلي:

{
  "name": "your-project",
  "version": "1.0.0",
  "description": "",
  "main": "src/server.js",
  "scripts": {
    "start": "node src/server.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

الآن، أنشئ ملفًا يُسمى Dockerfile (بدون امتداد). دعنا نكتب صورتنا!

 FROM node:lts-alpine
 COPY . /usr/src/app/
 WORKDIR /usr/src/app
 EXPOSE 8089
 ENTRYPOINT [ "npm" , "start" ]

دعنا نشرح هذا:

  1. أولاً، نحصل على صورة node من Docker Hub. نظرًا لأن الصور يتم حفظها بأسمائها، فإننا نميز الصور بواسطة علاماتها (tags). يمكنك التحقق من جميع العلامات هنا.
  2. بعد ذلك، نستخدم COPY لنسخ جميع الملفات في الدليل الحالي (باستخدام .) إلى دليل جديد في الحاوية يُسمى /usr/src/app. يتم إنشاء الدليل تلقائيًا. هذا ضروري لأننا نحتاج إلى جميع ملفات تطبيقنا هناك.
  3. الآن نغير دليل البدء الخاص بنا إلى الدليل /usr/src/app، حتى نتمكن من تشغيل الأشياء من الدليل الجذر لتطبيقنا.
  4. نكشف عن منفذنا (EXPOSE 8089).
  5. ونقول أنه بمجرد تشغيل حاويتنا، سنقوم بتنفيذ "npm start".

دعنا نبني الصورة عن طريق تشغيل docker build . -t simple-node-image. بهذه الطريقة سنقوم بوضع علامة على صورتنا وإعطائها اسمًا.

عملية بناء صورة Docker لتطبيق Node.js

سترى أنه سيقوم بإنشاء وتنزيل الصورة، جنبًا إلى جنب مع جميع الطبقات الضرورية. دعنا نشغل هذه الصورة بالأمر التالي:

docker run -p 80:8089 simple-node-image

نقوم بتعيين منفذنا 80 إلى المنفذ 8089 داخل الحاوية. يمكننا التحقق من ذلك عن طريق كتابة docker ps كما يلي:

التحقق من تشغيل حاوية Docker باستخدام الأمر docker ps

الآن حاول الوصول إلى localhost:80، وشاهد ما سيحدث:

عرض رسالة 'Hello from Docker!' في المتصفح بعد الوصول إلى localhost:80

ما الذي يُستخدم Docker من أجله؟ تطبيقات عملية متقدمة

الآن بعد أن رأينا كيفية بناء حاوية Docker، دعنا ننتقل إلى بعض الاستخدامات العملية لـ Docker وكيف يمكنك الاستفادة القصوى منه.

قواعد البيانات المؤقتة (Ephemeral databases)

هل سبق لك أن حاولت تطوير تطبيق يتطلب قاعدة بيانات للتشغيل؟ أو الأسوأ من ذلك، حاولت تشغيل تطبيق شخص آخر يحتاج إلى قاعدة بيانات لم تقم بتثبيتها؟ كان الحل القديم هو تثبيت قاعدة البيانات أولاً، ثم تشغيل التطبيق. مع Docker، ما عليك سوى تشغيل حاوية قاعدة البيانات. دعنا نشغل حاوية MongoDB بسيطة:

$ docker run -p 27017:27017 --name my-ephemeral-db mongo

هذا كل شيء! يمكنك الآن الوصول إلى قاعدة بياناتك من جهاز الكمبيوتر الخاص بك عبر المنفذ 27017، تمامًا كما تفعل عادةً.

قواعد البيانات الدائمة (Persistent databases)

المشكلة في المثال السابق هي أنه إذا قمت بإزالة الحاوية، فستفقد جميع بياناتك. إذن، ماذا يحدث إذا كنت ترغب في تشغيل قاعدة بيانات محلية دون الحاجة إلى تثبيتها، ولكن الاحتفاظ بالبيانات بعد حذفها؟ يمكنك ربط Docker بوحدة تخزين (volume)! عندما تربط Docker بوحدة تخزين محلية، فإنك تقوم بشكل أساسي بتركيب نظام ملفاتك في الحاوية أو العكس. دعنا نرى:

$ docker run -p 27017:27017 -v /home/my/path/to/db:/data/db --name my-persistent-db mongo

في هذا الأمر، نقوم بتركيب /data/db في /home/my/path/to/db. الآن إذا استخدمنا docker stop my-persistent-db و docker rm my-persistent-db، فستظل جميع بياناتنا مخزنة هناك. لاحقًا، إذا احتجنا إلى قاعدة البيانات مرة أخرى، يمكننا تركيبها باستخدام نفس الأمر، وستعود جميع البيانات.

أدوات الاستخدام لمرة واحدة (One-use tools)

شيء آخر يفعله جميع المطورين: نقوم بتثبيت تطبيقات نستخدمها مرة واحدة فقط. على سبيل المثال، واجهة سطر الأوامر البسيطة (CLI) للوصول إلى قاعدة البيانات القديمة، أو الواجهة الرسومية البسيطة (GUI) لخادم التكامل المستمر (CI server). تحتوي العديد من الأدوات بالفعل على حاويات Docker، ويمكنك استخدامها بهذه الطريقة، حتى لا تضطر إلى تثبيت أداة أخرى في جهاز الكمبيوتر المحمول الخاص بك. أفضل مثال هو Redis. يحتوي على redis-cli مدمج في حاوية أخرى، لذلك لا تحتاج إلى تثبيت redis-cli في واجهة الأوامر (shell) الخاصة بك إذا كنت بالكاد تستخدمه. دعنا نتخيل أنك تشغل مثيل Redis باستخدام docker run -d --name redis redis --bind 127.0.0.1 مربوطًا بواجهة المضيف المحلي (localhost interface). يمكنك الوصول إليه من خلال حاوية أخرى باستخدام:

$ docker run --rm -it --network container:redis redis-cli -h 127.0.0.1

تخبر العلامة --rm Docker أنه يجب إزالة الحاوية بمجرد إيقافها، بينما تخبر العلامتان -it أننا نريد جلسة تفاعلية (مع واجهة أوامر) وسنحتاج إلى طرفية (TTY).

تشغيل مكدسات كاملة (Run entire stacks)

إذا كنت بحاجة إلى اختبار تطبيق يعتمد على تطبيق آخر، فكيف ستفعل ذلك؟ يجعل Docker الأمر سهلاً من خلال توفير docker-compose. إنها أداة أخرى في صندوق أدواتك تسمح لك بترميز ملف docker-compose.yml يصف بيئتك. يبدو الملف كما يلي:

 version: "3.8"
 services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"
    ports:
      - "6379:6379"

كما ترى، نحن نحدد خدمتين، إحداهما تُسمى web وتشغل docker build على المسار web.build. هذا هو Dockerfile. بعد ذلك، تعرض المنفذ 5000 في كل من المضيف والحاوية. الخدمة الأخرى هي redis، والتي تسحب وتشغل صورة redis على المنفذ 6379. أفضل جزء هو أن طبقة الشبكة مشتركة، بعبارة أخرى، يمكنك الوصول إلى redis من خدمة web ببساطة عن طريق كتابة redis والمنفذ. يمكنك بدء هذا الملف باستخدام docker-compose up بسيط، ومشاهدة السحر يحدث.

الخلاصة التقنية

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

إن بنيته الطبقية، وكفاءته في استخدام الموارد، وطبيعته المؤقتة، تجعل منه حلاً مثاليًا لسيناريوهات مثل قواعد البيانات المؤقتة، وأدوات الاستخدام لمرة واحدة، وتكامل مسارات CI/CD، وتشغيل مكدسات تطبيقات كاملة. لقد أحدث Docker ثورة في كيفية بناء المطورين لتطبيقاتهم ونشرها، مما سمح لهم بالتركيز بشكل أكبر على الابتكار وتقليل الوقت المستغرق في إدارة البنية التحتية. في نهاية المطاف، Docker ليس مجرد تقنية، بل هو فلسفة عمل تهدف إلى تعزيز الإنتاجية والكفاءة في عالم البرمجيات المتطور باستمرار.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *