لو بناء الـ Docker image بتاعك بياخد 9 دقايق كل مرة بتغيّر فيها سطر واحد في الكود، المشكلة مش في السيرفر ولا في حجم الـ image. المشكلة في ترتيب ملف Dockerfile، وبالظبط في السطر اللي بتنسخ فيه الكود قبل ما تنسخ الـ dependencies.
Docker Layer Caching بالعربي: ليه الـ build بطيء وإزاي تصلّحه
المشكلة باختصار
كل build جديد من الصفر يعني استهلاك ضعف وقت المطور، بطء في الـ CI pipeline، وانتظار قبل كل deploy. السبب الغالب: الـ Docker layer cache مش شغّال لأن ترتيب التعليمات في الـ Dockerfile غلط. في المثال الفعلي اللي هنشوفه دلوقتي، build كان بياخد 9 دقايق و12 ثانية، نزل لـ 38 ثانية بعد إعادة ترتيب 5 سطور وتفعيل BuildKit.
مثال بسيط جدًا للمبتدئين
تخيّل إنك بتعمل ساندويتش كل يوم: عيش، جبنة، طماطم، زيتون، وفي الآخر بتحط بقدونس. لو كل يوم بتغيّر نوع البقدونس بس، هل معقول إنك تجيب عيش جديد وجبنة جديدة وطماطم جديدة من أول وجديد؟ طبعًا لأ. هتستخدم نفس المكونات السابقة المحفوظة في التلاجة، وتغيّر البقدونس بس.
Docker بيشتغل بنفس المنطق بالظبط. الـ image مش كتلة واحدة، هي طبقات (layers) مكدّسة فوق بعض. كل تعليمة RUN أو COPY أو ADD في الـ Dockerfile بتنتج طبقة جديدة. لما بتبني المرة التانية، Docker بيبص على كل طبقة ويسأل: "هل التعليمة دي وملفاتها اتغيّرت؟". لو لأ، بياخد الطبقة من الكاش بدل ما يعيد بناءها.
السبب التقني الدقيق
Docker image عبارة عن سلسلة طبقات read-only مبنية فوق بعض باستخدام union filesystem — افتراضيًا OverlayFS على Linux. كل instruction في الـ Dockerfile بتنتج layer ليها content-addressable hash (SHA256) محسوب من: نص التعليمة نفسها، وملفات الـ build context اللي دخلت فيها، وحالة الـ parent layer.
لما بتبني للمرة التانية، Docker بيقارن الـ hash المحسوب مع الـ cache المحلي. لو مطابق، بياخدها من الكاش في ميلي ثانية. لو مختلف (cache miss)، كل الطبقات اللي بعدها بتتعاد من الصفر، حتى لو محتواها ما اتغيّرش. القاعدة دي — cache invalidation cascades downward — هي سبب 90% من مشاكل البطء.
الخطأ الشائع اللي بيكسر الكاش
ده Dockerfile نموذجي لمشروع Node.js — الشكل اللي هتلاقيه في 70% من الـ repos على GitHub:
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["node", "dist/index.js"]
المشكلة في السطر التالت: COPY . .. أي تغيير في أي ملف — حتى README.md أو تعليق في ملف كود — بيغيّر hash الطبقة دي، وبيكسر الـ cache لكل اللي بعدها. ده معناه إن بتتعاد كاملة، واللي بتاخد لوحدها 4 دقايق في مشروع متوسط.