تسريع Docker Build في CI: من 12 دقيقة لدقيقتين بدون تغيير السيرفرات
لو الـ pipeline بتاعك بياخد 10 دقايق أو أكتر في خطوة docker build، المشكلة 90% منها مش في حجم الكود ولا قوة الـ runner. المشكلة إن الـ build بيعيد تنزيل ال dependencies كل مرة من الصفر. الحل اسمه BuildKit cache، وبتظبيط صح بيخلّي البناء التاني أسرع بـ 5× إلى 10×.
المشكلة باختصار
كل CI runner في GitHub Actions أو GitLab CI بيبدأ من جهاز نظيف. يعني أول ما docker build يبتدي، الـ Docker daemon ما عندوش أي layer مكاش من قبل. النتيجة: npm install أو pip install أو go mod download بيشتغل من الصفر في كل push. لو عندك مشروع متوسط بـ 800 dependency، ده ممكن ياخد 4-7 دقايق وحده، قبل ما يبدأ يعمل compile للكود.
ركز: مش كل الفرق التقنية بتلاحظ ده، لأن البناء المحلي عندهم بيكون سريع (في cache على الجهاز). يكتشفوا المشكلة لما الـ deploy يبتدي يتعطّل، ويبدأوا يفكروا في تغيير السيرفر أو تقسيم الـ image. الحل أبسط من كده بكتير.
مثال للمبتدئين: ليه الكاش مهم أصلاً
تخيّل إنك بتعمل عصير برتقال كل صباح. لو في كل مرة بتعصر برتقال، ترجع تشتري عصّارة جديدة من السوبرماركت، تطلّعها من الكرتونة، تغسلها، تركّبها، تعصر، ثم ترميها — هيبقى كل كوب عصير ياخد ساعة بدل دقيقتين.
الـ CI من غير cache بيعمل بالظبط نفس الكلام. كل مرة بيشتري كل الـ dependencies من الإنترنت، يفكها، ينصّبها، يستخدمها مرة واحدة، وبعدين الجهاز كله بيتمسح. الـ BuildKit cache بيقول للـ runner: «العصّارة ديت احتفظ بيها على الرف». المرة الجاية، بيفتح الرف ويعصر مباشرة.
التعريف العلمي بدقة
BuildKit هو الـ build engine الجديد لـ Docker (افتراضي من إصدار 23.0). بيختلف عن الـ legacy builder في حاجتين رئيسيتين: parallel layer execution، وaddressable cache منفصل عن نظام الـ filesystem. الـ cache mount هو directive جديد في الـ Dockerfile (# syntax=docker/dockerfile:1.7) بيقول للـ BuildKit: «الفولدر ده — مثلًا /root/.npm — احتفظ بمحتواه بين الـ builds في طبقة كاش منفصلة، حتى لو الـ layer اللي بيستخدمه اتغيّر».
الفرق المعماري المهم: في الـ legacy builder، الـ cache مرتبط بالـ layer hash. لو غيّرت سطر واحد قبل RUN npm install، الـ layer كله بيتحسب من جديد، وبتنزل الـ packages تاني. مع cache mount، الـ node_modules اللي اتنزلت قبل كده بتفضل موجودة، وnpm بيشوفها ويستخدم منها مباشرة.
الحل العملي خطوة بخطوة
هنبني pipeline في GitHub Actions ينقل الـ build من 12 دقيقة لأقل من دقيقتين. الافتراض إن عندك مشروع Node.js أو Python فيه Dockerfile متوسط الحجم (300MB-1GB image).