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

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

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

بداية

بدأ كل شيء في إحدى أمسيات شهر سبتمبر الممطرة عندما كنت أقوم بتنظيف جهاز استأجرته مقابل 5 دولارات على Digital Ocean والذي تجمد حتى الموت لأن Docker ملأ كل مساحة القرص المتاحة البالغة 24 جيجابايت بالصور والحاويات الخاصة به. كانت المفارقة هي أن كل هذه الصور والحاويات كانت مؤقتة ولم تكن هناك حاجة إليها إلا لاختبار وظائف تطبيقي في كل مرة يتم فيها إصدار إصدار جديد من بعض المكتبات أو الأطر. لقد حاولت كتابة نصوص shell وإعداد جدول cron لتنظيف القمامة، لكن هذا لم يساعد: في كل مرة كان ينتهي الأمر حتمًا باستهلاك مساحة القرص الخاصة بخادمي وتعليق الخادم (في أفضل الأحوال). في مرحلة ما، صادفت مقالاً حول كيفية تشغيل Jenkins في حاوية وكيف يمكنه إنشاء وحذف خطوط أنابيب البناء من خلال مقبس daemon docker الذي تم تمريره إليه. أعجبتني الفكرة، ولكنني قررت المضي قدمًا ومحاولة تجربة تشغيل 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 daemon لا يعمل حتى:

    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. اضغط على Enter. لقد عدنا إلى البرج.

من هذه النقطة فصاعدًا، يمكننا محاولة تشغيل حاويات أخرى داخل حاوية 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. تشغيل MySQL:

    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. نذهب إلى localhost في المتصفح، ونتأكد من أن الخادم يستجيب بـ "Hello World!".

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

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

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

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

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

شراء استضافة موثوقة للمواقع مع حماية DDoS وخوادم VPS VDS 🔥 اشترِ استضافة مواقع ويب موثوقة مع حماية من هجمات DDoS، وخوادم VPS وVDS | ProHoster