أكبر تأثير جاء من استخدام بناء دوكر متعدد المراحل. الصورة الأصلية كانت تتضمن كل ما هو ضروري لـ«بناء» التطبيق – المترجمات، أدوات التطوير، وذاكرات التخزين المؤقتة للحزم. لا شيء من هذه الأدوات مطلوب بمجرد تشغيل التطبيق. بتقسيم العملية إلى مرحلة 'بناء' ومرحلة 'تشغيل' نظيفة ومنفصلة، تم شحن الكود الأساسي للتطبيق والتبعيات الضرورية فقط. هذا وحده قلل الحجم بنحو 500 ميجابايت!
خطوة ذكية أخرى كانت اختيار صور أساسية أخف. بدلاً من استخدام صورة `node:20` الكاملة (التي تشبه نظام تشغيل دبيان كاملاً)، تحولوا إلى `node:20-slim`. هذا قلل مئات الميجابايت عن طريق إزالة المكونات غير الضرورية. بالنسبة للتطبيقات المترجمة إلى ثنائي واحد، مثل تلك المكتوبة بلغات Go أو Rust، يمكنك الذهاب أبعد من ذلك باستخدام صور 'distroless' (بدون توزيع)، والتي لا تحتوي تقريباً على شيء سوى تطبيقك – لا يوجد شل، لا مدير حزم، ولا أجزاء إضافية من نظام التشغيل. هذا لا يقلل حجم الصورة فحسب، بل يجعلها أكثر أماناً أيضاً. فقط تذكر، صورة distroless تعني عدم وجود شل لتصحيح الأخطاء داخل الحاوية.
يبني دوكر الصور طبقة تلو الأخرى، وإذا تغير أي شيء في طبقة سابقة، يتم إعادة بناء جميع الطبقات اللاحقة. ملف Dockerfile الأصلي كان ينسخ جميع أكواد المصدر «قبل» تثبيت التبعيات. هذا يعني أن كل تغيير صغير في الكود كان يجبر على إعادة تثبيت جميع التبعيات بالكامل. بنسخ ملف `package.json` أولاً، ثم تشغيل `npm ci` لتثبيت التبعيات، و«بعد ذلك» نسخ بقية الكود، يتم تخزين طبقة التبعيات مؤقتاً. هذا حول عملية إعادة البناء التي كانت تستغرق 4 دقائق إلى 20 ثانية فقط!
أخيراً، يمنع استخدام ملف `.dockerignore` نسخ الملفات غير الضرورية مثل تاريخ Git أو أدوات التطوير المحلية إلى الصورة. على الرغم من أن هذا قد لا يقلل بشكل كبير من الحجم النهائي للصورة، إلا أنه يسرع نقل سياق البناء، مما يجعل عمليات البناء أسرع. هذه التقنيات المباشرة تظهر أن تحسين صور دوكر الخاصة بك لا يتطلب تغييرات عميقة في الكود، بل يتطلب ممارسات بناء ذكية. الأمر يتعلق بالكفاءة وجعل سير عملك التطويري أكثر سلاسة بشكل ملحوظ.