مرحبا بالجميع! في مقالتي السابقة ، وعدت بالحديث عن إطلاق Docker في Docker والجوانب العملية لتطبيق هذا الدرس. لقد حان الوقت للحفاظ على وعدنا. ربما يجادل ديفو ذو خبرة أن أولئك الذين يحتاجون إلى Docker داخل Docker يرمون مقبس Docker من المضيف داخل الحاوية وهذا يكفي في 99٪ من الحالات. لكن لا تتعجل في رمي ملفات تعريف الارتباط في وجهي ، لأننا سنتحدث عن الإطلاق الحقيقي لـ Docker داخل Docker. يحتوي هذا الحل على العديد من مجالات التطبيق الممكنة ، وهذه المقالة تدور حول أحدها ، لذا استرخ وقم بتصويب ذراعيك أمامك.
بداية
بدأ كل شيء في أمطار تمطر في شهر سبتمبر عندما كنت أقوم بتنظيف سيارة مستأجرة Digital Ocean مقابل 5 دولارات ، والتي تم تعليقها ضيقًا لأن Docker ملأت مساحة القرص المتوفرة البالغة 24 غيغا بايت بصورها وحاوياتها. المفارقة هي أن كل هذه الصور والحاويات كانت عابرة وتحتاج فقط لاختبار أداء طلبي في كل مرة يتم فيها إصدار نسخة جديدة من مكتبة أو إطار عمل. حاولت كتابة نصوص صدفة وتكوين جدول التيجان لتنظيف القمامة ، لكن هذا لم يوفر: في كل مرة ، حتماً ، تبين أن مساحة القرص على الخادم الخاص بي قد تم تناولها وتعلق الخادم (في أحسن الأحوال). في مرحلة ما ، صادفت مقالًا حول كيفية تشغيل Jenkins في حاوية وكيف يمكن إنشاء خطوط أنابيب التجميع وحذفها من خلال مأخذ توصيل الجهاز الخفي الذي تم طرحه فيه. أعجبتني الفكرة ، لكنني قررت المضي قدمًا ومحاولة تجربة الإطلاق المباشر لـ Docker داخل Docker. بدا لي بعد ذلك قرارًا منطقيًا تمامًا بضخ صور عامل ميناء وإنشاء حاويات لجميع التطبيقات التي أحتاج إليها للاختبار داخل حاوية أخرى (دعنا نسميها حاوية التدريج). كانت الفكرة هي تشغيل حاوية التدريج بعلامة - rm ، والتي تقوم تلقائيًا بحذف الحاوية بأكملها بكل محتوياتها عندما تتوقف. لقد تفشت مع صورة عامل الميناء من Docker نفسه ( https://hub.docker.com/_/docker ) ، لكن تبين أن حجمها كبير جدًا ولم أتمكن من تشغيله حسب حاجتي وأردت المضي قدمًا بنفسي.
الممارسة. المخاريط
شرعت في جعل الحاوية تعمل حسب حاجتي واستمرت في تجاربي ، مما أدى إلى عدد لا يحصى من المخاريط. كانت نتيجة تعذيبي الذاتي هي الخوارزمية التالية:
نطلق حاوية الإرساء في وضع تفاعلي.
docker run --privileged -it docker:18.09.6
انتبه إلى إصدار الحاوية ، خطوة إلى اليمين أو إلى اليسار ويتحول DinD الخاص بك إلى قرع. في الواقع ، كل شيء ينهار في كثير من الأحيان مع إصدار نسخة جديدة.
يجب أن ندخل على الفور في قذيفة.
محاولة معرفة الحاويات التي تعمل (الإجابة: لا شيء) ، ولكن دعونا ننفذ الأمر على أي حال:
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
لنشغلها بنفسك:
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
نبدأ باش. وأخيرا عدنا في قذيفة المعتادة
حاول تشغيل عامل الإرساء مرة أخرى:
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 الخاصة بي:
https://github.com/alekslitvinenk/dind
أعطاني حل DinD العملي الفرصة لتشغيل Docker داخل Docker بشكل متكرر وإجراء تجارب أكثر جرأة.
إحدى هذه التجارب (الناجحة) مع تشغيل MySQL و Nodejs ، سأصفها الآن.
الأكثر نفاد الصبر يمكن أن نرى كيف كان هنا
لذلك ، لنبدأ:
إطلاق DinD بشكل تفاعلي. في هذا الإصدار من DinD ، نحتاج إلى تعيين جميع المنافذ التي يمكن أن تستخدمها حاويات الأطفال يدويًا (أعمل بالفعل على هذا)
docker run --privileged -it \ -p 80:8080 \ -p 3306:3306 \ alekslitvinenk/dind
نجد أنفسنا في bash ، من حيث يمكننا أن نبدأ على الفور في إطلاق الحاويات الفرعية.
نبدأ الخلية:
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.
نذهب إلى المضيف المحلي في المتصفح ، ونحن مقتنعون بأن الخادم يجيب "Hello World!".
في حالتي ، كانت تجربة حاويات السفن المرفقة إيجابية للغاية ، وسأواصل تطوير المشروع واستخدامه في التدريج. يبدو لي أن هذا هو الحل أكثر خفيفة الوزن بكثير من نفس Kubernetes و Jenkins X. ولكن هذا رأيي شخصي.
أعتقد أن هذا هو كل شيء لمقال اليوم. في المقالة التالية ، سوف أصف بتفصيل أكثر التجارب مع الإطلاق المتكرر لـ Docker في Docker وأدلة التثبيت في عمق الحاويات المتداخلة.
ملاحظة: إذا وجدت هذا المشروع مفيدًا ، فيرجى إعطائه علامة نجمية على GitHub وشوكة وإخبار أصدقائك.
تحرير 1 الأخطاء الثابتة ، التي تركز على 2 أشرطة الفيديو