بعض النصائح حول كيفية تسريع إنشاء صور Docker. على سبيل المثال ، حتى 30 ثانية

قبل أن تدخل الميزة مرحلة الإنتاج، في هذه الأيام التي تتسم بوجود منسقين معقدين وCI/CD، لا يزال هناك طريق طويل لنقطعه من الالتزام بالاختبارات والتسليم. في السابق، كان بإمكانك تحميل ملفات جديدة عبر FTP (لم يعد أحد يفعل ذلك، أليس كذلك؟)، وكانت عملية "النشر" تستغرق ثوانٍ. أنت الآن بحاجة إلى إنشاء طلب دمج والانتظار لفترة طويلة حتى تصل الميزة إلى المستخدمين.

جزء من هذا المسار هو بناء صورة Docker. في بعض الأحيان يستمر التجميع دقائق، وأحيانا عشرات الدقائق، والتي بالكاد يمكن أن تسمى طبيعية. في هذه المقالة، سنتناول تطبيقًا بسيطًا سنجمعه في صورة، ونطبق عدة طرق لتسريع عملية البناء، وننظر إلى الفروق الدقيقة في كيفية عمل هذه الطرق.

بعض النصائح حول كيفية تسريع إنشاء صور Docker. على سبيل المثال ، حتى 30 ثانية

لدينا خبرة جيدة في إنشاء ودعم المواقع الإعلامية: تاس, جرس, "جريدة", جمهورية... منذ وقت ليس ببعيد قمنا بتوسيع محفظتنا من خلال إطلاق موقع ويب خاص بالمنتج تذكير. وبينما تمت إضافة ميزات جديدة بسرعة وإصلاح الأخطاء القديمة، أصبح النشر البطيء مشكلة كبيرة.

نحن ننشر في GitLab. نحن نجمع الصور وندفعها إلى GitLab Registry ونطرحها في مرحلة الإنتاج. أطول شيء في هذه القائمة هو تجميع الصور. على سبيل المثال: بدون التحسين، استغرق كل إنشاء للواجهة الخلفية 14 دقيقة.

بعض النصائح حول كيفية تسريع إنشاء صور Docker. على سبيل المثال ، حتى 30 ثانية

وفي النهاية، أصبح من الواضح أننا لم يعد بإمكاننا العيش بهذه الطريقة، وجلسنا لمعرفة سبب استغراق الصور وقتًا طويلاً لجمعها. ونتيجة لذلك، تمكنا من تقليل وقت التجميع إلى 30 ثانية!

بعض النصائح حول كيفية تسريع إنشاء صور Docker. على سبيل المثال ، حتى 30 ثانية

بالنسبة لهذه المقالة، حتى لا تكون مرتبطة ببيئة التذكير، دعونا نلقي نظرة على مثال لتجميع تطبيق Angular فارغ. لذلك، دعونا ننشئ تطبيقنا:

ng n app

أضف PWA إليها (نحن تقدميون):

ng add @angular/pwa --project app

بينما يتم تنزيل مليون حزمة npm، فلنتعرف على كيفية عمل صورة عامل الإرساء. يوفر Docker القدرة على حزم التطبيقات وتشغيلها في بيئة معزولة تسمى الحاوية. بفضل العزلة، يمكنك تشغيل العديد من الحاويات في وقت واحد على خادم واحد. الحاويات أخف بكثير من الأجهزة الافتراضية لأنها تعمل مباشرة على نواة النظام. لتشغيل حاوية مع تطبيقنا، نحتاج أولاً إلى إنشاء صورة سنحزم فيها كل ما هو ضروري لتشغيل تطبيقنا. في الأساس، الصورة هي نسخة من نظام الملفات. على سبيل المثال، خذ ملف Dockerfile:

FROM node:12.16.2
WORKDIR /app
COPY . .
RUN npm ci
RUN npm run build --prod

ملف Dockerfile عبارة عن مجموعة من التعليمات؛ من خلال القيام بكل واحدة منها، سيقوم Docker بحفظ التغييرات على نظام الملفات وتراكبها على التغييرات السابقة. يقوم كل فريق بإنشاء طبقته الخاصة. والصورة النهائية عبارة عن طبقات مدمجة معًا.

ما هو مهم معرفته: يمكن لكل طبقة Docker تخزينها مؤقتًا. إذا لم يتغير شيء منذ البناء الأخير، فبدلا من تنفيذ الأمر، سيأخذ عامل الإرساء طبقة جاهزة. نظرًا لأن الزيادة الرئيسية في سرعة البناء ستكون بسبب استخدام ذاكرة التخزين المؤقت، فعند قياس سرعة البناء، سنولي اهتمامًا خاصًا لبناء صورة باستخدام ذاكرة تخزين مؤقت جاهزة. لذلك، خطوة بخطوة:

  1. نقوم بحذف الصور محليًا حتى لا تؤثر عمليات التشغيل السابقة على الاختبار.
    docker rmi $(docker images -q)
  2. نطلق البناء لأول مرة.
    time docker build -t app .
  3. نقوم بتغيير ملف src/index.html - فنحن نقلد عمل المبرمج.
  4. نقوم بتشغيل البناء مرة ثانية.
    time docker build -t app .

إذا تم تكوين بيئة إنشاء الصور بشكل صحيح (المزيد حول ذلك أدناه)، فعند بدء الإنشاء، سيكون لدى Docker بالفعل مجموعة من ذاكرات التخزين المؤقت على متنه. مهمتنا هي معرفة كيفية استخدام ذاكرة التخزين المؤقت حتى تتم عملية الإنشاء في أسرع وقت ممكن. وبما أننا نفترض أن تشغيل إصدار بدون ذاكرة تخزين مؤقت يحدث مرة واحدة فقط — المرة الأولى — فيمكننا بالتالي تجاهل مدى بطء تلك المرة الأولى. في الاختبارات، تكون الجولة الثانية من البناء أمرًا مهمًا بالنسبة لنا، عندما تكون المخابئ دافئة بالفعل ونصبح جاهزين لخبز الكعكة. ومع ذلك، ستؤثر بعض النصائح أيضًا على البناء الأول.

لنضع ملف Dockerfile الموصوف أعلاه في مجلد المشروع ونبدأ في الإنشاء. وقد تم تكثيف كافة القوائم لسهولة القراءة.

$ time docker build -t app .
Sending build context to Docker daemon 409MB
Step 1/5 : FROM node:12.16.2
Status: Downloaded newer image for node:12.16.2
Step 2/5 : WORKDIR /app
Step 3/5 : COPY . .
Step 4/5 : RUN npm ci
added 1357 packages in 22.47s
Step 5/5 : RUN npm run build --prod
Date: 2020-04-16T19:20:09.664Z - Hash: fffa0fddaa3425c55dd3 - Time: 37581ms
Successfully built c8c279335f46
Successfully tagged app:latest

real 5m4.541s
user 0m0.000s
sys 0m0.000s

نقوم بتغيير محتويات src/index.html وتشغيله مرة أخرى.

$ time docker build -t app .
Sending build context to Docker daemon 409MB
Step 1/5 : FROM node:12.16.2
Step 2/5 : WORKDIR /app
 ---> Using cache
Step 3/5 : COPY . .
Step 4/5 : RUN npm ci
added 1357 packages in 22.47s
Step 5/5 : RUN npm run build --prod
Date: 2020-04-16T19:26:26.587Z - Hash: fffa0fddaa3425c55dd3 - Time: 37902ms
Successfully built 79f335df92d3
Successfully tagged app:latest

real 3m33.262s
user 0m0.000s
sys 0m0.000s

لمعرفة ما إذا كانت لدينا الصورة، قم بتشغيل الأمر docker images:

REPOSITORY   TAG      IMAGE ID       CREATED              SIZE
app          latest   79f335df92d3   About a minute ago   1.74GB

قبل الإنشاء، يأخذ عامل الإرساء جميع الملفات الموجودة في السياق الحالي ويرسلها إلى البرنامج الخفي الخاص به Sending build context to Docker daemon 409MB. يتم تحديد سياق البناء باعتباره الوسيطة الأخيرة لأمر البناء. في حالتنا، هذا هو الدليل الحالي - "."، - ويقوم Docker بسحب كل ما لدينا في هذا المجلد. 409 ميجابايت هي مساحة كبيرة: فلنفكر في كيفية إصلاحها.

تقليل السياق

لتقليل السياق، هناك خياران. أو ضع جميع الملفات اللازمة للتجميع في مجلد منفصل وقم بتوجيه سياق عامل الإرساء إلى هذا المجلد. قد لا يكون هذا مناسبًا دائمًا، لذلك من الممكن تحديد الاستثناءات: ما لا ينبغي سحبه إلى السياق. للقيام بذلك، ضع ملف .dockerignore في المشروع وأشر إلى ما هو غير مطلوب للبناء:

.git
/node_modules

وقم بتشغيل الإنشاء مرة أخرى:

$ time docker build -t app .
Sending build context to Docker daemon 607.2kB
Step 1/5 : FROM node:12.16.2
Step 2/5 : WORKDIR /app
 ---> Using cache
Step 3/5 : COPY . .
Step 4/5 : RUN npm ci
added 1357 packages in 22.47s
Step 5/5 : RUN npm run build --prod
Date: 2020-04-16T19:33:54.338Z - Hash: fffa0fddaa3425c55dd3 - Time: 37313ms
Successfully built 4942f010792a
Successfully tagged app:latest

real 1m47.763s
user 0m0.000s
sys 0m0.000s

607.2 كيلو بايت أفضل بكثير من 409 ميجا بايت. قمنا أيضًا بتقليل حجم الصورة من 1.74 إلى 1.38 جيجابايت:

REPOSITORY   TAG      IMAGE ID       CREATED         SIZE
app          latest   4942f010792a   3 minutes ago   1.38GB

دعونا نحاول تقليل حجم الصورة بشكل أكبر.

نحن نستخدم جبال الألب

هناك طريقة أخرى لتوفير حجم الصورة وهي استخدام صورة رئيسية صغيرة. الصورة الأبوية هي الصورة التي يتم على أساسها إعداد صورتنا. يتم تحديد الطبقة السفلية بواسطة الأمر FROM في ملف دوكر. في حالتنا، نحن نستخدم صورة مبنية على Ubuntu والتي تم تثبيت Nodejs عليها بالفعل. و يزن...

$ docker images -a | grep node
node 12.16.2 406aa3abbc6c 17 minutes ago 916MB

... غيغابايت تقريبًا. يمكنك تقليل مستوى الصوت بشكل كبير باستخدام صورة تعتمد على Alpine Linux. Alpine هو نظام Linux صغير جدًا. تزن صورة عامل الإرساء الخاصة بـnodejs المستندة إلى جبال الألب 88.5 ميجابايت فقط. لذلك دعونا نستبدل صورتنا الحية في المنازل:

FROM node:12.16.2-alpine3.11
RUN apk --no-cache --update --virtual build-dependencies add 
    python 
    make 
    g++
WORKDIR /app
COPY . .
RUN npm ci
RUN npm run build --prod

كان علينا تثبيت بعض الأشياء الضرورية لبناء التطبيق. نعم، لا يتم إنشاء Angular بدون Python ¯(°_o)/¯

لكن حجم الصورة انخفض إلى 150 ميجابايت:

REPOSITORY   TAG      IMAGE ID       CREATED          SIZE
app          latest   aa031edc315a   22 minutes ago   761MB

دعونا نذهب أبعد من ذلك.

تجميع متعدد المراحل

ليس كل ما في الصورة هو ما نحتاجه في الإنتاج.

$ docker run app ls -lah
total 576K
drwxr-xr-x 1 root root 4.0K Apr 16 19:54 .
drwxr-xr-x 1 root root 4.0K Apr 16 20:00 ..
-rwxr-xr-x 1 root root 19 Apr 17 2020 .dockerignore
-rwxr-xr-x 1 root root 246 Apr 17 2020 .editorconfig
-rwxr-xr-x 1 root root 631 Apr 17 2020 .gitignore
-rwxr-xr-x 1 root root 181 Apr 17 2020 Dockerfile
-rwxr-xr-x 1 root root 1020 Apr 17 2020 README.md
-rwxr-xr-x 1 root root 3.6K Apr 17 2020 angular.json
-rwxr-xr-x 1 root root 429 Apr 17 2020 browserslist
drwxr-xr-x 3 root root 4.0K Apr 16 19:54 dist
drwxr-xr-x 3 root root 4.0K Apr 17 2020 e2e
-rwxr-xr-x 1 root root 1015 Apr 17 2020 karma.conf.js
-rwxr-xr-x 1 root root 620 Apr 17 2020 ngsw-config.json
drwxr-xr-x 1 root root 4.0K Apr 16 19:54 node_modules
-rwxr-xr-x 1 root root 494.9K Apr 17 2020 package-lock.json
-rwxr-xr-x 1 root root 1.3K Apr 17 2020 package.json
drwxr-xr-x 5 root root 4.0K Apr 17 2020 src
-rwxr-xr-x 1 root root 210 Apr 17 2020 tsconfig.app.json
-rwxr-xr-x 1 root root 489 Apr 17 2020 tsconfig.json
-rwxr-xr-x 1 root root 270 Apr 17 2020 tsconfig.spec.json
-rwxr-xr-x 1 root root 1.9K Apr 17 2020 tslint.json

استخدام docker run app ls -lah أطلقنا حاوية بناءً على صورتنا app ونفذ الأمر فيه ls -lahوبعد ذلك أكملت الحاوية عملها.

في الإنتاج نحتاج فقط إلى مجلد dist. في هذه الحالة، الملفات تحتاج بطريقة أو بأخرى إلى أن تعطى للخارج. يمكنك تشغيل بعض خوادم HTTP على العقدة. لكننا سنجعل الأمر أسهل. خمن كلمة روسية مكونة من أربعة أحرف "y". يمين! ينجينيكي. لنلتقط صورة باستخدام nginx، ونضع مجلدًا فيها dist وتكوين صغير:

server {
    listen 80 default_server;
    server_name localhost;
    charset utf-8;
    root /app/dist;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

سيساعدنا البناء متعدد المراحل على القيام بكل هذا. دعونا نغير ملف Dockerfile الخاص بنا:

FROM node:12.16.2-alpine3.11 as builder
RUN apk --no-cache --update --virtual build-dependencies add 
    python 
    make 
    g++
WORKDIR /app
COPY . .
RUN npm ci
RUN npm run build --prod

FROM nginx:1.17.10-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/static.conf /etc/nginx/conf.d
COPY --from=builder /app/dist/app .

الآن لدينا تعليماتين FROM في ملف Dockerfile، يقوم كل واحد منهم بتنفيذ خطوة بناء مختلفة. اتصلنا بالأول builder، ولكن بدءًا من آخر FROM، سيتم إعداد صورتنا النهائية. الخطوة الأخيرة هي نسخ قطعة أثرية من مجموعتنا في الخطوة السابقة إلى الصورة النهائية باستخدام nginx. انخفض حجم الصورة بشكل ملحوظ:

REPOSITORY   TAG      IMAGE ID       CREATED          SIZE
app          latest   2c6c5da07802   29 minutes ago   36MB

لنقم بتشغيل الحاوية التي تحتوي على صورتنا ونتأكد من أن كل شيء يعمل:

docker run -p8080:80 app

باستخدام الخيار -p8080:80، قمنا بإعادة توجيه المنفذ 8080 على الجهاز المضيف لدينا إلى المنفذ 80 داخل الحاوية حيث يعمل nginx. فتح في المتصفح http://localhost:8080/ ونرى طلبنا. كل شيء يعمل!

بعض النصائح حول كيفية تسريع إنشاء صور Docker. على سبيل المثال ، حتى 30 ثانية

يؤدي تقليل حجم الصورة من 1.74 جيجابايت إلى 36 ميجابايت إلى تقليل الوقت المستغرق لتسليم تطبيقك إلى مرحلة الإنتاج بشكل كبير. لكن دعنا نعود إلى وقت التجميع.

$ time docker build -t app .
Sending build context to Docker daemon 608.8kB
Step 1/11 : FROM node:12.16.2-alpine3.11 as builder
Step 2/11 : RUN apk --no-cache --update --virtual build-dependencies add python make g++
 ---> Using cache
Step 3/11 : WORKDIR /app
 ---> Using cache
Step 4/11 : COPY . .
Step 5/11 : RUN npm ci
added 1357 packages in 47.338s
Step 6/11 : RUN npm run build --prod
Date: 2020-04-16T21:16:03.899Z - Hash: fffa0fddaa3425c55dd3 - Time: 39948ms
 ---> 27f1479221e4
Step 7/11 : FROM nginx:stable-alpine
Step 8/11 : WORKDIR /app
 ---> Using cache
Step 9/11 : RUN rm /etc/nginx/conf.d/default.conf
 ---> Using cache
Step 10/11 : COPY nginx/static.conf /etc/nginx/conf.d
 ---> Using cache
Step 11/11 : COPY --from=builder /app/dist/app .
Successfully built d201471c91ad
Successfully tagged app:latest

real 2m17.700s
user 0m0.000s
sys 0m0.000s

تغيير ترتيب الطبقات

تم تخزين خطواتنا الثلاث الأولى مؤقتًا (تلميح Using cache). في الخطوة الرابعة، يتم نسخ كافة ملفات المشروع ويتم تثبيت التبعيات في الخطوة الخامسة RUN npm ci - بقدر 47.338 ثانية. لماذا إعادة تثبيت التبعيات في كل مرة إذا كانت تتغير نادرًا جدًا؟ دعونا نكتشف سبب عدم تخزينها مؤقتًا. النقطة المهمة هي أن Docker سيتحقق من طبقة تلو الأخرى لمعرفة ما إذا كان الأمر والملفات المرتبطة به قد تغيرت. في الخطوة الرابعة، نقوم بنسخ جميع ملفات مشروعنا، ومن بينها، بالطبع، هناك تغييرات، لذلك لا يأخذ Docker هذه الطبقة من ذاكرة التخزين المؤقت فحسب، بل أيضًا جميع الطبقات اللاحقة! دعونا نجري بعض التغييرات الصغيرة على ملف Dockerfile.

FROM node:12.16.2-alpine3.11 as builder
RUN apk --no-cache --update --virtual build-dependencies add 
    python 
    make 
    g++
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build --prod

FROM nginx:1.17.10-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/static.conf /etc/nginx/conf.d
COPY --from=builder /app/dist/app .

أولاً، يتم نسخ package.json وpackage-lock.json، ثم يتم تثبيت التبعيات، وبعد ذلك فقط يتم نسخ المشروع بأكمله. نتيجة ل:

$ time docker build -t app .
Sending build context to Docker daemon 608.8kB
Step 1/12 : FROM node:12.16.2-alpine3.11 as builder
Step 2/12 : RUN apk --no-cache --update --virtual build-dependencies add python make g++
 ---> Using cache
Step 3/12 : WORKDIR /app
 ---> Using cache
Step 4/12 : COPY package*.json ./
 ---> Using cache
Step 5/12 : RUN npm ci
 ---> Using cache
Step 6/12 : COPY . .
Step 7/12 : RUN npm run build --prod
Date: 2020-04-16T21:29:44.770Z - Hash: fffa0fddaa3425c55dd3 - Time: 38287ms
 ---> 1b9448c73558
Step 8/12 : FROM nginx:stable-alpine
Step 9/12 : WORKDIR /app
 ---> Using cache
Step 10/12 : RUN rm /etc/nginx/conf.d/default.conf
 ---> Using cache
Step 11/12 : COPY nginx/static.conf /etc/nginx/conf.d
 ---> Using cache
Step 12/12 : COPY --from=builder /app/dist/app .
Successfully built a44dd7c217c3
Successfully tagged app:latest

real 0m46.497s
user 0m0.000s
sys 0m0.000s

46 ثانية بدلاً من 3 دقائق - أفضل بكثير! الترتيب الصحيح للطبقات مهم: أولاً نقوم بنسخ ما لا يتغير، ثم ما يتغير نادرًا، وأخيرًا ما يتغير كثيرًا.

بعد ذلك، بضع كلمات حول تجميع الصور في أنظمة CI/CD.

استخدام الصور السابقة لذاكرة التخزين المؤقت

إذا استخدمنا نوعًا ما من حلول SaaS للبناء، فقد تكون ذاكرة التخزين المؤقت المحلية لـ Docker نظيفة وحديثة. لمنح عامل الإرساء مكانًا للحصول على الطبقات المخبوزة، أعطه الصورة المبنية السابقة.

لنأخذ مثالاً على بناء تطبيقنا في GitHub Actions. نحن نستخدم هذا التكوين

on:
  push:
    branches:
      - master

name: Test docker build

jobs:
  deploy:
    name: Build
    runs-on: ubuntu-latest
    env:
      IMAGE_NAME: docker.pkg.github.com/${{ github.repository }}/app
      IMAGE_TAG: ${{ github.sha }}

    steps:
    - name: Checkout
      uses: actions/checkout@v2

    - name: Login to GitHub Packages
      env:
        TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        docker login docker.pkg.github.com -u $GITHUB_ACTOR -p $TOKEN

    - name: Build
      run: |
        docker build 
          -t $IMAGE_NAME:$IMAGE_TAG 
          -t $IMAGE_NAME:latest 
          .

    - name: Push image to GitHub Packages
      run: |
        docker push $IMAGE_NAME:latest
        docker push $IMAGE_NAME:$IMAGE_TAG

    - name: Logout
      run: |
        docker logout docker.pkg.github.com

يتم تجميع الصورة ودفعها إلى حزم GitHub في دقيقتين و20 ثانية:

بعض النصائح حول كيفية تسريع إنشاء صور Docker. على سبيل المثال ، حتى 30 ثانية

الآن دعنا نغير البنية بحيث يتم استخدام ذاكرة التخزين المؤقت بناءً على الصور المبنية السابقة:

on:
  push:
    branches:
      - master

name: Test docker build

jobs:
  deploy:
    name: Build
    runs-on: ubuntu-latest
    env:
      IMAGE_NAME: docker.pkg.github.com/${{ github.repository }}/app
      IMAGE_TAG: ${{ github.sha }}

    steps:
    - name: Checkout
      uses: actions/checkout@v2

    - name: Login to GitHub Packages
      env:
        TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        docker login docker.pkg.github.com -u $GITHUB_ACTOR -p $TOKEN

    - name: Pull latest images
      run: |
        docker pull $IMAGE_NAME:latest || true
        docker pull $IMAGE_NAME-builder-stage:latest || true

    - name: Images list
      run: |
        docker images

    - name: Build
      run: |
        docker build 
          --target builder 
          --cache-from $IMAGE_NAME-builder-stage:latest 
          -t $IMAGE_NAME-builder-stage 
          .
        docker build 
          --cache-from $IMAGE_NAME-builder-stage:latest 
          --cache-from $IMAGE_NAME:latest 
          -t $IMAGE_NAME:$IMAGE_TAG 
          -t $IMAGE_NAME:latest 
          .

    - name: Push image to GitHub Packages
      run: |
        docker push $IMAGE_NAME-builder-stage:latest
        docker push $IMAGE_NAME:latest
        docker push $IMAGE_NAME:$IMAGE_TAG

    - name: Logout
      run: |
        docker logout docker.pkg.github.com

نحتاج أولاً أن نخبرك عن سبب إطلاق أمرين build. الحقيقة هي أنه في التجميع متعدد المراحل، ستكون الصورة الناتجة عبارة عن مجموعة من الطبقات من المرحلة الأخيرة. في هذه الحالة، لن يتم تضمين طبقات من الطبقات السابقة في الصورة. لذلك، عند استخدام الصورة النهائية من بناء سابق، لن يتمكن Docker من العثور على طبقات جاهزة لبناء الصورة باستخدام Nodejs (مرحلة البناء). من أجل حل هذه المشكلة، يتم إنشاء صورة وسيطة $IMAGE_NAME-builder-stage ويتم دفعه إلى حزم GitHub بحيث يمكن استخدامه في إنشاء لاحق كمصدر للتخزين المؤقت.

بعض النصائح حول كيفية تسريع إنشاء صور Docker. على سبيل المثال ، حتى 30 ثانية

تم تقليل إجمالي وقت التجميع إلى دقيقة ونصف. يتم قضاء نصف دقيقة في سحب الصور السابقة.

التصوير المسبق

هناك طريقة أخرى لحل مشكلة ذاكرة التخزين المؤقت النظيفة لـ Docker وهي نقل بعض الطبقات إلى ملف Dockerfile آخر، وإنشائها بشكل منفصل، ودفعها إلى سجل الحاوية واستخدامها كأصل.

نقوم بإنشاء صورة Nodejs الخاصة بنا لإنشاء تطبيق Angular. قم بإنشاء Dockerfile.node في المشروع

FROM node:12.16.2-alpine3.11
RUN apk --no-cache --update --virtual build-dependencies add 
    python 
    make 
    g++

نقوم بجمع صورة عامة ودفعها في Docker Hub:

docker build -t exsmund/node-for-angular -f Dockerfile.node .
docker push exsmund/node-for-angular:latest

الآن في ملف Dockerfile الرئيسي، نستخدم الصورة النهائية:

FROM exsmund/node-for-angular:latest as builder
...

في مثالنا، لم ينخفض ​​وقت الإنشاء، لكن الصور المعدة مسبقًا يمكن أن تكون مفيدة إذا كان لديك العديد من المشاريع وكان عليك تثبيت نفس التبعيات في كل منها.

بعض النصائح حول كيفية تسريع إنشاء صور Docker. على سبيل المثال ، حتى 30 ثانية

لقد بحثنا في عدة طرق لتسريع إنشاء صور عامل الإرساء. إذا كنت تريد أن تتم عملية النشر بسرعة، فحاول استخدام هذا في مشروعك:

  • تقليل السياق؛
  • استخدام صور الوالدين الصغيرة؛
  • تجميع متعدد المراحل
  • تغيير ترتيب التعليمات في ملف Dockerfile للاستفادة بكفاءة من ذاكرة التخزين المؤقت؛
  • إعداد ذاكرة تخزين مؤقت في أنظمة CI/CD؛
  • الإنشاء الأولي للصور.

آمل أن يوضح المثال كيفية عمل Docker، وستكون قادرًا على تكوين النشر على النحو الأمثل. من أجل اللعب بالأمثلة الواردة في المقالة، تم إنشاء مستودع https://github.com/devopsprodigy/test-docker-build.

المصدر: www.habr.com

إضافة تعليق