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

بداية
بدأ كل شيء في إحدى أمسيات شهر سبتمبر الممطرة عندما كنت أقوم بتنظيف جهاز استأجرته مقابل 5 دولارات على Digital Ocean والذي تجمد حتى الموت لأن Docker ملأ كل مساحة القرص المتاحة البالغة 24 جيجابايت بالصور والحاويات الخاصة به. كانت المفارقة هي أن كل هذه الصور والحاويات كانت مؤقتة ولم تكن هناك حاجة إليها إلا لاختبار وظائف تطبيقي في كل مرة يتم فيها إصدار إصدار جديد من بعض المكتبات أو الأطر. لقد حاولت كتابة نصوص shell وإعداد جدول cron لتنظيف القمامة، لكن هذا لم يساعد: في كل مرة كان ينتهي الأمر حتمًا باستهلاك مساحة القرص الخاصة بخادمي وتعليق الخادم (في أفضل الأحوال). في مرحلة ما، صادفت مقالاً حول كيفية تشغيل Jenkins في حاوية وكيف يمكنه إنشاء وحذف خطوط أنابيب البناء من خلال مقبس daemon docker الذي تم تمريره إليه. أعجبتني الفكرة، ولكنني قررت المضي قدمًا ومحاولة تجربة تشغيل Docker مباشرةً داخل Docker. لقد بدا الأمر وكأنه حل منطقي بالنسبة لي بعد ذلك لتنزيل صور Docker وإنشاء حاويات لجميع التطبيقات التي أحتاجها للاختبار داخل حاوية أخرى (دعنا نسميها حاوية مؤقتة). كانت الفكرة هي تشغيل حاوية مؤقتة باستخدام العلم -rm، والذي سيقوم تلقائيًا بحذف الحاوية بأكملها وكل محتوياتها عند إيقافها. لقد قمت بالبحث باستخدام صورة Docker من Docker نفسها (), ولكن تبين أن الأمر كان مرهقًا للغاية ولم أتمكن أبدًا من جعله يعمل بالطريقة التي أحتاجها وأردت أن أمر بالعملية بأكملها بنفسي.
يمارس. المخاريط
لقد حددت لنفسي هدفًا وهو جعل الحاوية تعمل بالطريقة التي أحتاجها واستمريت في تجاربي، مما أدى إلى إنتاج عدد لا يحصى من المخاريط. وكانت نتيجة تعذيبي لنفسي الخوارزمية التالية:
نقوم بتشغيل حاوية Docker في الوضع التفاعلي.
docker run --privileged -it docker:18.09.6انتبه إلى إصدار الحاوية، واتجه إلى اليمين أو اليسار وسيتحول DinD الخاص بك إلى قرع. في الواقع، تنكسر الأشياء في كثير من الأحيان عندما يصدر إصدار جديد.
يتعين علينا الدخول إلى القوقعة فورًا.دعنا نحاول معرفة الحاويات التي تعمل (الإجابة: لا يوجد)، ولكن دعنا ننفذ الأمر على أي حال:
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دعونا نديرها بأنفسنا:
dockerd &مفاجأة غير سارة أخرى:
failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: Iptables not foundنقوم بتثبيت حزم iptables وbash (من المؤكد أنه من الممتع العمل في bash مقارنة بالعمل في sh):
apk add --no-cache iptables bashإطلاق باش. لقد عدنا أخيرًا إلى قوقعتنا المعتادة
دعنا نحاول تشغيل 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اضغط على Enter. لقد عدنا إلى البرج.
من هذه النقطة فصاعدًا، يمكننا محاولة تشغيل حاويات أخرى داخل حاوية Docker الخاصة بنا، ولكن ماذا لو أردنا تشغيل حاوية Docker أخرى داخل حاوية Docker الخاصة بنا أو حدث خطأ ما وتعطل الحاوية؟ ابدأ من جديد.
حاوية DinD الخاصة والتجارب الجديدة
لتجنب تكرار الخطوات المذكورة أعلاه مرارًا وتكرارًا، قمت بإنشاء حاوية DinD الخاصة بي:
لقد منحني حل DinD العامل القدرة على تشغيل Docker داخل Docker بشكل متكرر وإجراء المزيد من التجارب المغامرة.
سأقوم الآن بوصف إحدى هذه التجارب (الناجحة) عند تشغيل MySQL وNodejs.
الأكثر نفاد صبر يمكن أن يرى كيف كان الأمر هنا

لذلك دعونا نبدأ:
نطلق DinD في الوضع التفاعلي. في هذا الإصدار من DinD، نحتاج إلى تعيين جميع المنافذ التي يمكن لحاوياتنا الفرعية استخدامها يدويًا (أنا أعمل على هذا بالفعل)
docker run --privileged -it -p 80:8080 -p 3306:3306 alekslitvinenk/dindندخل إلى bash، حيث يمكننا البدء فورًا في تشغيل الحاويات الفرعية.
تشغيل MySQL:
docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysqlنقوم بالاتصال بقاعدة البيانات بنفس الطريقة التي نتصل بها بها محليًا. دعونا نتأكد من أن كل شيء يعمل.
نطلق الحاوية الثانية:
docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-serverيرجى ملاحظة أن تعيين المنفذ هنا سيكون بالضبط 8080:8080، نظرًا لأننا قمنا بالفعل بتعيين المنفذ 80 من المضيف إلى الحاوية الرئيسية على المنفذ 8080.
نذهب إلى localhost في المتصفح، ونتأكد من أن الخادم يستجيب بـ "Hello World!".
في حالتي، كانت التجربة باستخدام حاويات Docker المتداخلة إيجابية للغاية وسأستمر في تطوير المشروع واستخدامه في المرحلة التجريبية. يبدو لي أن هذا الحل أخف بكثير من نفس Kubernetes وJenkins X. لكن هذا رأيي الشخصي.
أعتقد أن هذا كل شيء لمقال اليوم. في المقالة التالية سوف أصف بمزيد من التفصيل التجارب التي أجريت على بدء تشغيل Docker المتكرر في Docker وتركيب الدلائل عميقًا في حاويات متداخلة.
PS إذا وجدت هذا المشروع مفيدًا، فيرجى منحه نجمة على GitHub، ونسخه وإخبار أصدقائك.
Edit1 تم إصلاح الأخطاء، وتم التركيز على مقطعي فيديو
المصدر: www.habr.com
