เคล็ดลับบางประการเกี่ยวกับวิธีเพิ่มความเร็วในการสร้างอิมเมจ Docker เช่น สูงสุด 30 วินาที

ก่อนที่คุณลักษณะจะเข้าสู่การใช้งานจริง ในยุคปัจจุบันของผู้จัดเตรียมที่ซับซ้อนและ CI/CD หนทางอีกยาวไกลในการเปลี่ยนจากการคอมมิตไปสู่การทดสอบและการส่งมอบ ก่อนหน้านี้ คุณสามารถอัปโหลดไฟล์ใหม่ผ่าน FTP ได้ (ไม่มีใครทำเช่นนั้นอีกต่อไปแล้วใช่ไหม) และกระบวนการ "ปรับใช้" ใช้เวลาไม่กี่วินาที ตอนนี้คุณต้องสร้างคำขอรวมและรอเป็นเวลานานเพื่อให้ฟีเจอร์เข้าถึงผู้ใช้

ส่วนหนึ่งของเส้นทางนี้คือการสร้างอิมเมจนักเทียบท่า บางครั้งการชุมนุมอาจกินเวลาไม่กี่นาที บางครั้งอาจถึงสิบนาที ซึ่งแทบจะเรียกได้ว่าเป็นเรื่องปกติเลยทีเดียว ในบทความนี้ เราจะนำแอปพลิเคชันง่ายๆ ที่เราจะรวมไว้ในรูปภาพ ใช้วิธีการต่างๆ มากมายเพื่อเร่งการสร้าง และดูความแตกต่างเล็กๆ น้อยๆ ของวิธีทำงานเหล่านี้

เคล็ดลับบางประการเกี่ยวกับวิธีเพิ่มความเร็วในการสร้างอิมเมจ Docker เช่น สูงสุด 30 วินาที

เรามีประสบการณ์ที่ดีในการสร้างและสนับสนุนเว็บไซต์สื่อ: เอสเอส, เบลล์, "โนวายา กาเซต้า", สาธารณรัฐ… ไม่นานมานี้เราได้ขยายพอร์ตโฟลิโอของเราด้วยการเปิดตัวเว็บไซต์ผลิตภัณฑ์ เตือน- และในขณะที่มีการเพิ่มคุณสมบัติใหม่ๆ อย่างรวดเร็วและข้อบกพร่องเก่าๆ ได้รับการแก้ไขแล้ว การใช้งานที่ช้าก็กลายเป็นปัญหาใหญ่

เราปรับใช้กับ GitLab เรารวบรวมรูปภาพ พุชไปที่ GitLab Registry และเผยแพร่สู่การใช้งานจริง สิ่งที่ยาวที่สุดในรายการนี้คือการประกอบภาพ ตัวอย่างเช่น หากไม่มีการเพิ่มประสิทธิภาพ การสร้างแบ็กเอนด์แต่ละรายการจะใช้เวลา 14 นาที

เคล็ดลับบางประการเกี่ยวกับวิธีเพิ่มความเร็วในการสร้างอิมเมจ Docker เช่น สูงสุด 30 วินาที

ในท้ายที่สุด มันก็ชัดเจนว่าเราไม่สามารถใช้ชีวิตแบบนี้ได้อีกต่อไป และเรานั่งลงเพื่อดูว่าเหตุใดจึงใช้เวลานานมากในการรวบรวมภาพ เป็นผลให้เราสามารถลดเวลาการประกอบลงเหลือ 30 วินาที!

เคล็ดลับบางประการเกี่ยวกับวิธีเพิ่มความเร็วในการสร้างอิมเมจ Docker เช่น สูงสุด 30 วินาที

สำหรับบทความนี้ เพื่อไม่ให้เชื่อมโยงกับสภาพแวดล้อมของ Reminder เรามาดูตัวอย่างการประกอบแอปพลิเคชัน Angular ที่ว่างเปล่ากัน เรามาสร้างแอปพลิเคชันของเรากันดีกว่า:

ng n app

เพิ่ม PWA เข้าไป (เรามีความก้าวหน้า):

ng add @angular/pwa --project app

ในขณะที่กำลังดาวน์โหลดแพ็กเกจจำนวนหนึ่งล้าน npm เรามาดูกันว่าอิมเมจนักเทียบท่าทำงานอย่างไร นักเทียบท่ามอบความสามารถในการจัดทำแพ็คเกจแอปพลิเคชันและรันในสภาพแวดล้อมแบบแยกที่เรียกว่าคอนเทนเนอร์ ด้วยการแยกส่วน คุณสามารถเรียกใช้คอนเทนเนอร์จำนวนมากพร้อมกันบนเซิร์ฟเวอร์เดียวได้ คอนเทนเนอร์มีน้ำหนักเบากว่าเครื่องเสมือนมากเนื่องจากทำงานบนเคอร์เนลของระบบโดยตรง ในการรันคอนเทนเนอร์ด้วยแอปพลิเคชันของเรา ก่อนอื่นเราต้องสร้างอิมเมจซึ่งเราจะจัดแพ็คเกจทุกสิ่งที่จำเป็นสำหรับแอปพลิเคชันของเราในการทำงาน โดยพื้นฐานแล้ว รูปภาพคือการคัดลอกของระบบไฟล์ ตัวอย่างเช่น ใช้ 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- บริบทการสร้างถูกระบุเป็นอาร์กิวเมนต์สุดท้ายของคำสั่ง build ในกรณีของเรานี่คือไดเร็กทอรีปัจจุบัน - “.” - และ Docker จะลากทุกสิ่งที่เรามีในโฟลเดอร์นี้ 409 MB เยอะมาก ลองคิดดูว่าจะแก้ไขอย่างไร

การลดบริบท

เพื่อลดบริบท มีสองตัวเลือก หรือใส่ไฟล์ทั้งหมดที่จำเป็นสำหรับการประกอบในโฟลเดอร์แยกต่างหากและชี้บริบทนักเทียบท่าไปที่โฟลเดอร์นี้ สิ่งนี้อาจไม่สะดวกเสมอไป ดังนั้นจึงเป็นไปได้ที่จะระบุข้อยกเว้น: สิ่งที่ไม่ควรลากเข้าไปในบริบท เมื่อต้องการทำเช่นนี้ ให้วางไฟล์ .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 KB ดีกว่า 409 MB มาก นอกจากนี้เรายังลดขนาดรูปภาพจาก 1.74 เป็น 1.38 GB:

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

ลองลดขนาดของภาพให้เล็กลงอีก

เราใช้อัลไพน์

อีกวิธีหนึ่งในการบันทึกขนาดรูปภาพคือการใช้รูปภาพหลักที่มีขนาดเล็ก รูปภาพผู้ปกครองคือรูปภาพที่รูปภาพของเราเตรียมไว้ ชั้นล่างสุดถูกกำหนดโดยคำสั่ง FROM в Dockerfile. В нашем случае мы используем образ на основе Ubuntu, в котором уже стоит nodejs. И весит он …

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

… почти гигабайт. Изрядно сократить объем можно, используя образ на основе Alpine Linux. Alpine — это очень маленький линукс. Докер-образ для nodejs на основе alpine весит всего 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 zel(°_o)/ap

แต่ขนาดภาพลดลงเหลือ 150 MB:

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 บางตัวบน nodejs แต่เราจะทำให้มันง่ายขึ้น เดาคำภาษารัสเซียที่มีตัวอักษรสี่ตัว "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 GB เป็น 36 MB ช่วยลดเวลาที่ใช้ในการส่งแอปพลิเคชันของคุณไปสู่การใช้งานจริงได้อย่างมาก แต่ขอย้อนกลับไปเวลาประกอบ

$ 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 อื่น สร้างมันแยกกัน พุชเข้าไปใน Container Registry และใช้เป็นพาเรนต์

เราสร้างอิมเมจ nodejs ของเราเองเพื่อสร้างแอปพลิเคชันเชิงมุม สร้าง 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.

ที่มา: will.com

ซื้อโฮสติ้งที่เชื่อถือได้สำหรับไซต์ที่มีการป้องกัน DDoS เซิร์ฟเวอร์ VPS VDS 🔥 ซื้อบริการเว็บโฮสติ้งที่เชื่อถือได้ พร้อมระบบป้องกัน DDoS และเซิร์ฟเวอร์ VPS/VDS | ProHoster