كيف قمت بتشغيل Docker داخل Docker وما خرج منه

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

كيف قمت بتشغيل Docker داخل Docker وما خرج منه

بداية

بدأ كل شيء في أمسية ممطرة من شهر سبتمبر عندما كنت أقوم بتنظيف الجهاز الذي استأجرته مقابل 5 دولارات من Digital Ocean، والذي تم تجميده بسبب قيام Docker بملء جميع مساحة القرص المتوفرة البالغة 24 غيغابايت بصوره وحاوياته. المفارقة هي أن كل هذه الصور والحاويات كانت عابرة ولم تكن هناك حاجة إليها إلا لاختبار أداء تطبيقي في كل مرة يتم فيها إصدار نسخة جديدة من المكتبة أو إطار العمل. حاولت كتابة نصوص برمجية خاصة بالصدفة وإعداد جدول زمني لتنظيف القمامة، لكن ذلك لم يساعد: في كل مرة كان الأمر ينتهي حتمًا باستهلاك مساحة قرص الخادم الخاص بي وتعليق الخادم (في أحسن الأحوال). في مرحلة ما، صادفت مقالًا حول كيفية تشغيل Jenkins في حاوية وكيف يمكنه إنشاء وحذف خطوط أنابيب البناء من خلال مأخذ توصيل Docker Daemon الذي تم توجيهه إليه. أعجبتني الفكرة، لكنني قررت المضي قدمًا ومحاولة تجربة تشغيل Docker مباشرة داخل Docker. في ذلك الوقت، بدا لي أن تنزيل صور Docker وإنشاء حاويات لجميع التطبيقات التي أحتاجها للاختبار داخل حاوية أخرى (دعنا نسميها حاوية التدريج) هو الحل المنطقي تمامًا بالنسبة لي. كانت الفكرة هي بدء حاوية مرحلية باستخدام العلامة -rm، والتي تحذف الحاوية بأكملها وجميع محتوياتها تلقائيًا عند إيقافها. لقد تلاعبت بصورة Docker من Docker نفسها (https://hub.docker.com/_/docker)، ولكن تبين أن الأمر مرهق للغاية ولم أتمكن أبدًا من جعله يعمل بالطريقة التي أحتاجها وأردت المضي قدمًا بنفسي.

يمارس. المخاريط

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

  1. نقوم بتشغيل حاوية Docker في الوضع التفاعلي.

    docker run --privileged -it docker:18.09.6

    انتبه إلى إصدار الحاوية، تحرك يمينًا أو يسارًا وسيتحول DinD الخاص بك إلى قرع. في الواقع، تتعطل الأمور كثيرًا عند إصدار إصدار جديد.
    يجب أن ندخل على الفور في القشرة.

  2. نحن نحاول معرفة أي الحاويات قيد التشغيل (الإجابة: لا شيء)، ولكن دعونا ننفذ الأمر على أية حال:

    docker ps

    سوف تتفاجأ قليلاً، ولكن يتبين أن برنامج Docker الخفي لا يعمل حتى:

    error during connect: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 
    192.168.65.1:53: no such host

  3. دعونا نديرها بأنفسنا:

    dockerd &

    مفاجأة أخرى غير سارة:

    failed to start daemon: Error initializing network controller: error obtaining controller instance: failed 
    to create NAT chain DOCKER: Iptables not found

  4. قم بتثبيت حزم iptables وbash (كل شيء أكثر متعة للعمل في bash منه في sh):

    apk add --no-cache iptables bash

  5. دعونا نطلق باش. وأخيرا عدنا إلى القشرة المعتادة

  6. دعنا نحاول تشغيل Docker مرة أخرى:

    dockerd &

    يجب أن نرى ورقة طويلة من السجلات تنتهي بـ:

    INFO[2019-11-25T19:51:19.448080400Z] Daemon has completed initialization          
    INFO[2019-11-25T19:51:19.474439300Z] API listen on /var/run/docker.sock

  7. اضغط دخول. لقد عدنا إلى الباش.

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

حاوية DinD الخاصة والتجارب الجديدة

كيف قمت بتشغيل Docker داخل Docker وما خرج منه
لتجنب تكرار الخطوات المذكورة أعلاه مرارًا وتكرارًا، قمت بإنشاء حاوية DinD الخاصة بي:

https://github.com/alekslitvinenk/dind

لقد منحني حل DinD العملي القدرة على تشغيل Docker داخل Docker بشكل متكرر وإجراء المزيد من التجارب المغامرة.
سأصف إحدى هذه التجارب (الناجحة) لتشغيل MySQL وNodejs الآن.
يمكن لمن نفاد صبرهم أن يروا كيف كان الأمر هنا

لذلك دعونا نبدأ:

  1. نطلق DinD في الوضع التفاعلي. في هذا الإصدار من DinD، نحتاج إلى تعيين جميع المنافذ التي يمكن أن تستخدمها حاوياتنا الفرعية يدويًا (أنا أعمل على هذا بالفعل)

    docker run --privileged -it 
    -p 80:8080 
    -p 3306:3306 
    alekslitvinenk/dind

    وصلنا إلى bash، حيث يمكننا البدء فورًا في إطلاق الحاويات الفرعية.

  2. إطلاق الخلية:

    docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysql

  3. نحن نتصل بقاعدة البيانات بنفس الطريقة التي نتصل بها محليًا. دعونا نتأكد من أن كل شيء يعمل.

  4. إطلاق الحاوية الثانية:

    docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-server

    يرجى ملاحظة أن تعيين المنفذ سيكون بالضبط 8080:8080، نظرًا لأننا قمنا بالفعل بتعيين المنفذ 80 من المضيف إلى الحاوية الأصلية إلى المنفذ 8080.

  5. نذهب إلى المضيف المحلي في المتصفح، ونتأكد من أن الخادم يستجيب "Hello World!"

في حالتي، تبين أن تجربة حاويات Docker المتداخلة كانت إيجابية للغاية وسأستمر في تطوير المشروع واستخدامه للتشغيل المرحلي. يبدو لي أن هذا حل خفيف الوزن أكثر بكثير من حل Kubernetes وJenkins X. لكن هذا هو رأيي الشخصي.

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

PS إذا وجدت هذا المشروع مفيدًا، فيرجى منحه نجمة على GitHub، ثم قم بتقسيمه وأخبر أصدقائك.

Edit1 تم تصحيح الأخطاء، مع التركيز على مقطعي فيديو

المصدر: www.habr.com

إضافة تعليق