НСсколько совСтов ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ ΡƒΡΠΊΠΎΡ€ΠΈΡ‚ΡŒ сборку Docker-ΠΎΠ±Ρ€Π°Π·ΠΎΠ². НапримСр, Π΄ΠΎ 30 сСкунд

ΠŸΡ€Π΅ΠΆΠ΄Π΅ Ρ‡Π΅ΠΌ Ρ„ΠΈΡ‡Π° ΠΏΠΎΠΏΠ°Π΄Π΅Ρ‚ Π½Π° ΠΏΡ€ΠΎΠ΄, Π² нашС врСмя слоТных оркСстраторов ΠΈ CI/CD прСдстоит ΠΏΡ€ΠΎΠΉΡ‚ΠΈ Π΄ΠΎΠ»Π³ΠΈΠΉ ΠΏΡƒΡ‚ΡŒ ΠΎΡ‚ ΠΊΠΎΠΌΠΌΠΈΡ‚Π° Π΄ΠΎ тСстов ΠΈ доставки. РаньшС ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ ΠΊΠΈΠ½ΡƒΡ‚ΡŒ Π½ΠΎΠ²Ρ‹Π΅ Ρ„Π°ΠΉΠ»Ρ‹ ΠΏΠΎ FTP (Ρ‚Π°ΠΊ большС Ρ‚Π°ΠΊ Π½ΠΈΠΊΡ‚ΠΎ Π½Π΅ Π΄Π΅Π»Π°Π΅Ρ‚, Π²Π΅Ρ€Π½ΠΎ?), ΠΈ процСсс «дСплоя» Π·Π°Π½ΠΈΠΌΠ°Π» сСкунды. Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΆΠ΅ Π½Π°Π΄ΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ merge request ΠΈ ΠΆΠ΄Π°Ρ‚ΡŒ Π½Π΅ΠΌΠ°Π»ΠΎΠ΅ врСмя, ΠΏΠΎΠΊΠ° Ρ„ΠΈΡ‡Π° добСрётся Π΄ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ.

Π§Π°ΡΡ‚ΡŒ этого ΠΏΡƒΡ‚ΠΈ β€” сборка Docker-ΠΎΠ±Ρ€Π°Π·Π°. Иногда сборка длится ΠΌΠΈΠ½ΡƒΡ‚Ρ‹, ΠΈΠ½ΠΎΠ³Π΄Π° β€” дСсятки ΠΌΠΈΠ½ΡƒΡ‚, Ρ‡Ρ‚ΠΎ слоТно Π½Π°Π·Π²Π°Ρ‚ΡŒ Π½ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΌ. Π’ Π΄Π°Π½Π½ΠΎΠΉ ΡΡ‚Π°Ρ‚ΡŒΠ΅ Π²ΠΎΠ·ΡŒΠΌΡ‘ΠΌ простоС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΡƒΠΏΠ°ΠΊΡƒΠ΅ΠΌ Π² ΠΎΠ±Ρ€Π°Π·, ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠΌ нСсколько ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² для ускорСния сборки ΠΈ рассмотрим Π½ΡŽΠ°Π½ΡΡ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹ этих ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ².

НСсколько совСтов ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ ΡƒΡΠΊΠΎΡ€ΠΈΡ‚ΡŒ сборку Docker-ΠΎΠ±Ρ€Π°Π·ΠΎΠ². НапримСр, Π΄ΠΎ 30 сСкунд

Π£ нас Π½Π΅ΠΏΠ»ΠΎΡ…ΠΎΠΉ ΠΎΠΏΡ‹Ρ‚ создания ΠΈ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ сайтов БМИ: ВАББ, The Bell, "Новая Π³Π°Π·Π΅Ρ‚Π°", Republic… НС Ρ‚Π°ΠΊ Π΄Π°Π²Π½ΠΎ ΠΌΡ‹ ΠΏΠΎΠΏΠΎΠ»Π½ΠΈΠ»ΠΈ ΠΏΠΎΡ€Ρ‚Ρ„ΠΎΠ»ΠΈΠΎ, выпустив Π² ΠΏΡ€ΠΎΠ΄ сайт Reminder. И ΠΏΠΎΠΊΠ° быстро Π΄ΠΎΠΏΠΈΠ»ΠΈΠ²Π°Π»ΠΈ Π½ΠΎΠ²Ρ‹Π΅ Ρ„ΠΈΡ‡ΠΈ ΠΈ Ρ‡ΠΈΠ½ΠΈΠ»ΠΈ старыС Π±Π°Π³ΠΈ, ΠΌΠ΅Π΄Π»Π΅Π½Π½Ρ‹ΠΉ Π΄Π΅ΠΏΠ»ΠΎΠΉ стал большой ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉ.

Π”Π΅ΠΏΠ»ΠΎΠΉ ΠΌΡ‹ Π΄Π΅Π»Π°Π΅ΠΌ Π½Π° GitLab. Π‘ΠΎΠ±ΠΈΡ€Π°Π΅ΠΌ ΠΎΠ±Ρ€Π°Π·Ρ‹, ΠΏΡƒΡˆΠΈΠΌ Π² GitLab Registry ΠΈ раскатываСм Π½Π° ΠΏΡ€ΠΎΠ΄Π΅. Π’ этом спискС самоС Π΄ΠΎΠ»Π³ΠΎΠ΅ β€” это сборка ΠΎΠ±Ρ€Π°Π·ΠΎΠ². Для ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°: Π±Π΅Π· ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ каТдая сборка бэкСнда Π·Π°Π½ΠΈΠΌΠ°Π»Π° 14 ΠΌΠΈΠ½ΡƒΡ‚.

НСсколько совСтов ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ ΡƒΡΠΊΠΎΡ€ΠΈΡ‚ΡŒ сборку Docker-ΠΎΠ±Ρ€Π°Π·ΠΎΠ². НапримСр, Π΄ΠΎ 30 сСкунд

Π’ ΠΊΠΎΠ½Ρ†Π΅ ΠΊΠΎΠ½Ρ†ΠΎΠ² стало понятно, Ρ‡Ρ‚ΠΎ Ρ‚Π°ΠΊ ΠΆΠΈΡ‚ΡŒ большС нСльзя, ΠΈ ΠΌΡ‹ сСли Ρ€Π°Π·ΠΎΠ±Ρ€Π°Ρ‚ΡŒΡΡ, ΠΏΠΎΡ‡Π΅ΠΌΡƒ ΠΎΠ±Ρ€Π°Π·Ρ‹ ΡΠΎΠ±ΠΈΡ€Π°ΡŽΡ‚ΡΡ ΡΡ‚ΠΎΠ»ΡŒΠΊΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ. Π’ ΠΈΡ‚ΠΎΠ³Π΅ ΡƒΠ΄Π°Π»ΠΎΡΡŒ ΡΠΎΠΊΡ€Π°Ρ‚ΠΈΡ‚ΡŒ врСмя сборки Π΄ΠΎ 30 сСкунд!

НСсколько совСтов ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ ΡƒΡΠΊΠΎΡ€ΠΈΡ‚ΡŒ сборку Docker-ΠΎΠ±Ρ€Π°Π·ΠΎΠ². НапримСр, Π΄ΠΎ 30 сСкунд

Для Π΄Π°Π½Π½ΠΎΠΉ ΡΡ‚Π°Ρ‚ΡŒΠΈ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ ΠΏΡ€ΠΈΠ²ΡΠ·Ρ‹Π²Π°Ρ‚ΡŒΡΡ ΠΊ ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΡŽ Reminder’Π°, рассмотрим ΠΏΡ€ΠΈΠΌΠ΅Ρ€ сборки пустого прилоТСния Π½Π° Angular. Π˜Ρ‚Π°ΠΊ, создаём нашС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅:

ng n app

ДобавляСм Π² Π½Π΅Π³ΠΎ PWA (ΠΌΡ‹ ΠΆΠ΅ прогрСссивныС):

ng add @angular/pwa --project app

Пока скачиваСтся ΠΌΠΈΠ»Π»ΠΈΠΎΠ½ npm-ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², Π΄Π°Π²Π°ΠΉΡ‚Π΅ разбСрСмся, ΠΊΠ°ΠΊ устроСн docker-ΠΎΠ±Ρ€Π°Π·. Docker прСдоставляСт Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΡƒΠΏΠ°ΠΊΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ прилоТСния ΠΈ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ ΠΈΡ… Π² ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΌ ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ называСтся ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€. Благодаря изоляции ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ ΠΌΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠ² Π½Π° ΠΎΠ΄Π½ΠΎΠΌ сСрвСрС. ΠšΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π»Π΅Π³Ρ‡Π΅ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Ρ… машин, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ Π½Π° ядрС систСмы. Π§Ρ‚ΠΎΠ±Ρ‹ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ с нашим ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΠΌ, Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ сначала ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΎΠ±Ρ€Π°Π·, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΠΌΡ‹ ΡƒΠΏΠ°ΠΊΡƒΠ΅ΠΌ всё, Ρ‡Ρ‚ΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ нашСго прилоТСния. По сути ΠΎΠ±Ρ€Π°Π· β€” это слСпок Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠΉ систСмы. К ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ, Π²ΠΎΠ·ΡŒΠΌΡ‘ΠΌ Dockerfile:

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

Dockerfile β€” это Π½Π°Π±ΠΎΡ€ инструкций; выполняя ΠΊΠ°ΠΆΠ΄ΡƒΡŽ ΠΈΠ· Π½ΠΈΡ…, Docker Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΡ…Ρ€Π°Π½ΡΡ‚ΡŒ измСнСния Π² Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠΉ систСмС ΠΈ Π½Π°ΠΊΠ»Π°Π΄Ρ‹Π²Π°Ρ‚ΡŒ ΠΈΡ… Π½Π° ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠ΅. КаТдая ΠΊΠΎΠΌΠ°Π½Π΄Π° создаёт свой слой. А Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π· β€” это ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½Ρ‘Π½Π½Ρ‹Π΅ вмСстС слои.

Π§Ρ‚ΠΎ Π²Π°ΠΆΠ½ΠΎ Π·Π½Π°Ρ‚ΡŒ: ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ слой Π΄ΠΎΠΊΠ΅Ρ€ ΡƒΠΌΠ΅Π΅Ρ‚ ΠΊΡΡˆΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ. Если Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ измСнилось с ΠΏΡ€ΠΎΡˆΠ»ΠΎΠΉ сборки, Ρ‚ΠΎ вмСсто выполнСния ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ Π΄ΠΎΠΊΠ΅Ρ€ Π²ΠΎΠ·ΡŒΠΌΡ‘Ρ‚ ΡƒΠΆΠ΅ Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΉ слой. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ основной прирост Π² скорости сборки Π±ΡƒΠ΄Π΅Ρ‚ Π·Π° счСт использования кэша, Π² Π·Π°ΠΌΠ΅Ρ€Π°Ρ… скорости сборки Π±ΡƒΠ΄Π΅ΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π°Ρ‚ΡŒ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ ΠΈΠΌΠ΅Π½Π½ΠΎ Π½Π° сборку ΠΎΠ±Ρ€Π°Π·Π° с Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΌ кэшСм. Π˜Ρ‚Π°ΠΊ, ΠΏΠΎ шагам:

  1. УдаляСм ΠΎΠ±Ρ€Π°Π·Ρ‹ локально, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠ΅ запуски Π½Π΅ влияли Π½Π° тСст.
    docker rmi $(docker images -q)
  2. ЗапускаСм Π±ΠΈΠ»Π΄ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Ρ€Π°Π·.
    time docker build -t app .
  3. МСняСм Ρ„Π°ΠΉΠ» src/index.html β€” ΠΈΠΌΠΈΡ‚ΠΈΡ€ΡƒΠ΅ΠΌ Ρ€Π°Π±ΠΎΡ‚Ρƒ программиста.
  4. ЗапускаСм Π±ΠΈΠ»Π΄ Π²Ρ‚ΠΎΡ€ΠΎΠΉ Ρ€Π°Π·.
    time docker build -t app .

Если срСду для сборки ΠΎΠ±Ρ€Π°Π·ΠΎΠ² Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ (ΠΎ Ρ‡Π΅ΠΌ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ Π½ΠΈΠΆΠ΅), Ρ‚ΠΎ Π΄ΠΎΠΊΠ΅Ρ€ ΠΏΡ€ΠΈ запускС сборки ΡƒΠΆΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ Π½Π° Π±ΠΎΡ€Ρ‚Ρƒ ΠΊΡƒΡ‡ΠΊΡƒ кэшСй. Наша Π·Π°Π΄Π°Ρ‡Π° β€” Π½Π°ΡƒΡ‡ΠΈΡ‚ΡŒΡΡ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ кэш Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ сборка ΠΏΡ€ΠΎΡˆΠ»Π° максимально быстро. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΌΡ‹ ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΠΌ, Ρ‡Ρ‚ΠΎ запуск сборки Π±Π΅Π· кэша происходит всСго ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π· β€” самый ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ, β€” стало Π±Ρ‹Ρ‚ΡŒ, ΠΌΠΎΠΆΠ΅ΠΌ ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎ, насколько ΠΌΠ΅Π΄Π»Π΅Π½Π½Ρ‹ΠΌ Π±Ρ‹Π» этот ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Ρ€Π°Π·. Π’ тСстах Π½Π°ΠΌ Π²Π°ΠΆΠ΅Π½ Π²Ρ‚ΠΎΡ€ΠΎΠΉ запуск сборки, ΠΊΠΎΠ³Π΄Π° кэши ΡƒΠΆΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π΅Ρ‚Ρ‹ ΠΈ ΠΌΡ‹ Π³ΠΎΡ‚ΠΎΠ²Ρ‹ ΠΏΠ΅Ρ‡ΡŒ наш ΠΏΠΈΡ€ΠΎΠ³. Π’Π΅ΠΌ Π½Π΅ ΠΌΠ΅Π½Π΅Π΅, Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ совСты скаТутся Π½Π° ΠΏΠ΅Ρ€Π²ΠΎΠΉ сборкС Ρ‚ΠΎΠΆΠ΅.

ПолоТим 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. Π’ нашСм случаС это тСкущая дирСктория β€” Β«.Β», β€” ΠΈ Π΄ΠΎΠΊΠ΅Ρ€ Ρ‚Π°Ρ‰ΠΈΡ‚ всё, Ρ‡Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Ρƒ нас Π² этой ΠΏΠ°ΠΏΠΊΠ΅. 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

Π”Π°Π²Π°ΠΉΡ‚Π΅ ΠΏΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ Π΅Ρ‰Ρ‘ ΡƒΠΌΠ΅Π½ΡŒΡˆΠΈΡ‚ΡŒ Ρ€Π°Π·ΠΌΠ΅Ρ€ ΠΎΠ±Ρ€Π°Π·Π°.

Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Alpine

Π•Ρ‰Ρ‘ ΠΎΠ΄ΠΈΠ½ способ ΡΡΠΊΠΎΠ½ΠΎΠΌΠΈΡ‚ΡŒ Π½Π° Ρ€Π°Π·ΠΌΠ΅Ρ€Π΅ ΠΎΠ±Ρ€Π°Π·Π° β€” ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ малСнький Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ ΠΎΠ±Ρ€Π°Π·. Π ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ ΠΎΠ±Ρ€Π°Π· β€” это ΠΎΠ±Ρ€Π°Π·, Π½Π° основС ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ готовится наш ΠΎΠ±Ρ€Π°Π·. НиТний слой указываСтся ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ 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 Π½Π΅ собираСтся Π±Π΅Π· ΠΏΠΈΡ‚ΠΎΠ½Π° Β―(Β°_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-сСрвСр Π½Π° nodejs. Но ΠΌΡ‹ сдСлаСм ΠΏΡ€ΠΎΡ‰Π΅. Π£Π³Π°Π΄Π°ΠΉΡ‚Π΅ русскоС слово, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅ Π±ΡƒΠΊΠ²Ρ‹ Β«Ρ‹Β». ΠŸΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ! ЫнТыныксы. Π’ΠΎΠ·ΡŒΠΌΡ‘ΠΌ ΠΎΠ±Ρ€Π°Π· с nginx, ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ Π² Π½Π΅Π³ΠΎ ΠΏΠ°ΠΏΠΊΡƒ dist ΠΈ нСбольшой ΠΊΠΎΠ½Ρ„ΠΈΠ³:

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

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

Π­Ρ‚ΠΎ всё ΠΏΡ€ΠΎΠ²Π΅Ρ€Π½ΡƒΡ‚ΡŒ Π½Π°ΠΌ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ multi-stage build. ИзмСним наш 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.338s. Π—Π°Ρ‡Π΅ΠΌ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π· Π·Π°Π½ΠΎΠ²ΠΎ ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ зависимости, Ссли ΠΎΠ½ΠΈ ΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ ΠΎΡ‡Π΅Π½ΡŒ Ρ€Π΅Π΄ΠΊΠΎ? Π”Π°Π²Π°ΠΉΡ‚Π΅ разбСрСмся, ΠΏΠΎΡ‡Π΅ΠΌΡƒ ΠΎΠ½ΠΈ Π½Π΅ Π·Π°ΠΊΡΡˆΠΈΡ€ΠΎΠ²Π°Π»ΠΈΡΡŒ. Π”Π΅Π»ΠΎ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π΄ΠΎΠΊΠ΅Ρ€ провСрят слой Π·Π° слоСм, Π½Π΅ помСнялась Π»ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Π° ΠΈ Ρ„Π°ΠΉΠ»Ρ‹, связанныС с Π½Π΅ΠΉ. На Ρ‡Π΅Ρ‚Π²Ρ‘Ρ€Ρ‚ΠΎΠΌ шагС ΠΌΡ‹ ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ всС Ρ„Π°ΠΉΠ»Ρ‹ нашСго ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°, ΠΈ срСди Π½ΠΈΡ…, ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎ ΠΆΠ΅, Π΅ΡΡ‚ΡŒ измСнСния, поэтому Π΄ΠΎΠΊΠ΅Ρ€ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π΅ Π±Π΅Ρ€Π΅Ρ‚ ΠΈΠ· кэша этот слой, Π½ΠΎ ΠΈ всС ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅! Π”Π°Π²Π°ΠΉΡ‚Π΅ внСсём нСбольшиС измСнСния Π² 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-Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅, Ρ‚ΠΎ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ кэш Π΄ΠΎΠΊΠ΅Ρ€Π° ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ чист ΠΈ свСТ. Π§Ρ‚ΠΎΠ±Ρ‹ Π΄ΠΎΠΊΠ΅Ρ€Ρƒ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΊΡƒΠ΄Π° Π²Π·ΡΡ‚ΡŒ испСчСнныС слои, Π΄Π°ΠΉΡ‚Π΅ Π΅ΠΌΡƒ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΉ собранный ΠΎΠ±Ρ€Π°Π·.

Рассмотрим для ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° сборку нашСго прилоТСния Π² 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 Packages Π·Π° Π΄Π²Π΅ ΠΌΠΈΠ½ΡƒΡ‚Ρ‹ ΠΈ 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 Π½Π΅ смоТСт Π½Π°ΠΉΡ‚ΠΈ Π³ΠΎΡ‚ΠΎΠ²Ρ‹Π΅ слои для сборки ΠΎΠ±Ρ€Π°Π·Π° c nodejs (стСйдТ builder). Для Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ эту ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ, создаётся ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π· $IMAGE_NAME-builder-stage ΠΈ отправляСтся Π² GitHub Packages, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π΅Π³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ сборкС ΠΊΠ°ΠΊ источник кэша.

НСсколько совСтов ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ ΡƒΡΠΊΠΎΡ€ΠΈΡ‚ΡŒ сборку Docker-ΠΎΠ±Ρ€Π°Π·ΠΎΠ². НапримСр, Π΄ΠΎ 30 сСкунд

ΠžΠ±Ρ‰Π΅Π΅ врСмя сборки ΡΠΎΠΊΡ€Π°Ρ‚ΠΈΠ»ΠΎΡΡŒ Π΄ΠΎ ΠΏΠΎΠ»ΡƒΡ‚ΠΎΡ€Π° ΠΌΠΈΠ½ΡƒΡ‚. ΠŸΠΎΠ»ΠΌΠΈΠ½ΡƒΡ‚Ρ‹ тратится Π½Π° подтягиваниС ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΡ… ΠΎΠ±Ρ€Π°Π·ΠΎΠ².

ΠŸΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ созданиС ΠΎΠ±Ρ€Π°Π·ΠΎΠ²

Π•Ρ‰Ρ‘ ΠΎΠ΄ΠΈΠ½ способ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ чистого кэша Π΄ΠΎΠΊΠ΅Ρ€Π° β€” Ρ‡Π°ΡΡ‚ΡŒ слоёв вынСсти Π² Π΄Ρ€ΡƒΠ³ΠΎΠΉ Dockerfile, ΡΠΎΠ±Ρ€Π°Ρ‚ΡŒ Π΅Π³ΠΎ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ, Π·Π°ΠΏΡƒΡˆΠΈΡ‚ΡŒ Π² Container Registry ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠ°ΠΊ Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ.

Π‘ΠΎΠ·Π΄Π°Ρ‘ΠΌ свой ΠΎΠ±Ρ€Π°Π· 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.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com