ืขื˜ืœืขื›ืข ืขืฆื•ืช ืื•ื™ืฃ ื•ื•ื™ ืฆื• ืคืึทืจื’ื™ื›ืขืจืŸ ื“ื™ ื‘ื™ืœื“ ืคื•ืŸ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ืขืจ. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืึทืจื•ื™ืฃ ืฆื• 30 ืกืขืงื•ื ื“ืขืก

ืื™ื™ื“ืขืจ ืึท ืฉื˜ืจื™ืš ืงื•ืžื˜ ืื™ืŸ ืคึผืจืึธื“ื•ืงืฆื™ืข, ืื™ืŸ ื“ื™ ื˜ืขื’ ืคื•ืŸ ืงืึธืžืคึผืœืขืงืก ืึธืจืงืขืกื˜ืจื™ื™ื˜ืขืจื– ืื•ืŸ CI / CD, ืขืก ืื™ื– ืึท ืœืึทื ื’ ื•ื•ืขื’ ืฆื• ื’ื™ื™ืŸ ืคื•ืŸ ื™ื‘ืขืจื’ืขื‘ืŸ ืฆื• ื˜ืขืกืฅ ืื•ืŸ ืขืงืกืคึผืจืขืก. ื‘ื™ื– ืึทื”ืขืจ, ืื™ืจ ืงืขืŸ ืฆื•ืคึฟืขืœื™ืงืขืจ ื ื™ื™ึทืข ื˜ืขืงืขืก ื“ื•ืจืš ืคื˜ืคึผ (ืงื™ื™ืŸ ืื™ื™ื ืขืจ ื˜ื•ื˜ ื“ืึธืก ืขื ื™ืžืึธืจ, ืจืขื›ื˜?), ืื•ืŸ ื“ื™ "ื“ื™ืคึผืœื•ื™ืžืึทื ื˜" ืคึผืจืึธืฆืขืก ื’ืขื ื•ืžืขืŸ ืกืขืงื•ื ื“ืขืก. ืื™ืฆื˜ ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืฉืึทืคึฟืŸ ืึท ืฆื•ื ื•ื™ืคื’ื™ืกืŸ ื‘ืขื˜ืŸ ืื•ืŸ ื•ื•ืึทืจื˜ืŸ ืึท ืœืึทื ื’ ืฆื™ื™ึทื˜ ืคึฟืึทืจ ื“ื™ ืฉื˜ืจื™ืš ืฆื• ื“ืขืจื’ืจื™ื™ื›ืŸ ื“ื™ ื ื™ืฆืขืจืก.

ื˜ื™ื™ืœ ืคื•ืŸ ื“ืขื ื“ืจืš ืื™ื– ืฆื• ื‘ื•ื™ืขืŸ ืึท ื“ืึธืงืขืจ ื‘ื™ืœื“. ืืžืืœ ื’ืขื“ื•ื™ืขืจื˜ ื“ื™ ืืกื™ืคื” ืžื™ื ื•ื˜ืŸ, ืืžืืœ ืฆืขื ื“ืœื™ื’ืขืจ ืžื™ื ื•ื˜ืŸ, ื•ื•ืืก ืžืขืŸ ืงืขืŸ ืงื•ื™ื ืจื•ืคืŸ ื ืืจืžืืœ. ืื™ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ, ืžื™ืจ ื•ื•ืขืœืŸ ื ืขืžืขืŸ ืึท ืคึผืฉื•ื˜ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืึทื– ืžื™ืจ ืคึผืึทืงืŸ ืื™ืŸ ืึท ื‘ื™ืœื“, ืฆื•ืœื™ื™ื’ืŸ ืขื˜ืœืขื›ืข ืžืขื˜ื”ืึธื“ืก ืฆื• ืคืึทืจื’ื™ื›ืขืจืŸ ื“ื™ ื‘ื•ื™ืขืŸ, ืื•ืŸ ืงื•ืง ืื™ืŸ ื“ื™ ื ื•ืึทื ืกื™ื– ืคื•ืŸ ื•ื•ื™ ื“ื™ ืžืขื˜ื”ืึธื“ืก ืึทืจื‘ืขื˜.

ืขื˜ืœืขื›ืข ืขืฆื•ืช ืื•ื™ืฃ ื•ื•ื™ ืฆื• ืคืึทืจื’ื™ื›ืขืจืŸ ื“ื™ ื‘ื™ืœื“ ืคื•ืŸ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ืขืจ. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืึทืจื•ื™ืฃ ืฆื• 30 ืกืขืงื•ื ื“ืขืก

ืžื™ืจ ื”ืึธื‘ืŸ ื’ื•ื˜ ื“ืขืจืคืึทืจื•ื ื’ ืื™ืŸ ืงืจื™ื™ื™ื˜ื™ื ื’ ืื•ืŸ ืฉื˜ื™ืฆืŸ ืžืขื“ื™ืข ื•ื•ืขื‘ืกื™ื˜ืขืก: ื˜ืึทืก, ื“ืขืจ ื‘ืขืœ, "ื ืฒึทืข ืฆืฒึทื˜ื•ื ื’", ืจืขืคึผื•ื‘ืœื™ืง... ื ื™ื˜ ืœืึทื ื’ ืฆื•ืจื™ืง ืžื™ืจ ื™ืงืกืคึผืึทื ื“ื™ื“ ืื•ื ื“ื–ืขืจ ืคึผืึธืจื˜ืคืขืœ ื“ื•ืจืš ืจื™ืœื™ืกื™ื ื’ ืึท ืคึผืจืึธื“ื•ืงื˜ ื•ื•ืขื‘ื–ื™ื™ื˜ืœ ื“ืขืจืžืึธื ื•ื ื’. ืื•ืŸ ื‘ืฉืขืช ื ื™ื™ึท ืคึฟืขื™ึดืงื™ื™ื˜ืŸ ื–ืขื ืขืŸ ื’ืขืฉื•ื•ื™ื ื“ ืฆื•ื’ืขื’ืขื‘ืŸ ืื•ืŸ ืึทืœื˜ ื‘ืึทื’ื– ื–ืขื ืขืŸ ืคืึทืจืคืขืกื˜ื™ืงื˜, ืคึผืึทืžืขืœืขืš ื“ื™ืคึผืœื•ื™ืžืึทื ื˜ ื’ืขื•ื•ืืจืŸ ืึท ื’ืจื•ื™ืก ืคึผืจืึธื‘ืœืขื.

ืžื™ืจ ืฆืขื•ื•ื™ืงืœืขืŸ ืฆื• GitLab. ืžื™ืจ ืงืœื™ื™ึทื‘ืŸ ื‘ื™ืœื“ืขืจ, ืฉื˜ื•ืคึผืŸ ื–ื™ื™ ืฆื• GitLab ืจืขื’ื™ืกื˜ืจื™ ืื•ืŸ ืจืึธื•ืœื“ ื–ื™ื™ ืื•ื™ืก ืฆื• ืคึผืจืึธื“ื•ืงืฆื™ืข. ื“ื™ ืœืึธื ื’ืขืกื˜ ื–ืึทืš ืื•ื™ืฃ ื“ืขื ืจืฉื™ืžื” ืื™ื– ืึทืกืขืžื‘ืึทืœื™ื ื’ ื‘ื™ืœื“ืขืจ. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ: ืึธืŸ ืึทืคึผื˜ืึทืžืึทื–ื™ื™ืฉืึทืŸ, ื™ืขื“ืขืจ ื‘ืึทืงืขื ื“ ื‘ื•ื™ืขืŸ ื’ืขื ื•ืžืขืŸ 14 ืžื™ื ื•ื˜.

ืขื˜ืœืขื›ืข ืขืฆื•ืช ืื•ื™ืฃ ื•ื•ื™ ืฆื• ืคืึทืจื’ื™ื›ืขืจืŸ ื“ื™ ื‘ื™ืœื“ ืคื•ืŸ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ืขืจ. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืึทืจื•ื™ืฃ ืฆื• 30 ืกืขืงื•ื ื“ืขืก

ืฆื•ื ืกื•ืฃ ืื™ื– ืงืœืึธืจ ื’ืขื•ื•ืึธืจืŸ, ืึทื– ืžื™ืจ ืงืขื ืขืŸ ืžืขืจ ื ื™ืฉื˜ ืึทื–ื•ื™ ืœืขื‘ืŸ, ืื•ืŸ ืžื™ืจ ื”ืึธื‘ืŸ ื–ื™ืš ืึทื•ื•ืขืงื’ืขื–ืขืฆื˜ ืื•ื™ืกืฆื•ืคึฟืึธืจืฉืŸ, ื•ื•ืึธืก ื“ื™ ื‘ื™ืœื“ืขืจ ื ืขืžืขืŸ ืึทื–ื•ื™ ืœืึทื ื’ ืฆื• ื–ืึทืžืœืขืŸ. ื•ื•ื™ ืึท ืจืขื–ื•ืœื˜ืึทื˜, ืžื™ืจ ื’ืขืจืื˜ืŸ ืฆื• ืจืขื“ื•ืฆื™ืจืŸ ื“ื™ ืคึฟืึทืจื–ืึทืžืœื•ื ื’ ืฆื™ื™ื˜ ืฆื• 30 ืกืขืงื•ื ื“ืขืก!

ืขื˜ืœืขื›ืข ืขืฆื•ืช ืื•ื™ืฃ ื•ื•ื™ ืฆื• ืคืึทืจื’ื™ื›ืขืจืŸ ื“ื™ ื‘ื™ืœื“ ืคื•ืŸ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ืขืจ. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืึทืจื•ื™ืฃ ืฆื• 30 ืกืขืงื•ื ื“ืขืก

ืคึฟืึทืจ ื“ืขื ืึทืจื˜ื™ืงืœ, ืื™ืŸ ืกื“ืจ ื ื™ืฉื˜ ืฆื• ื–ื™ื™ืŸ ื˜ื™ื™ื“ ืฆื• ื“ืขืจ ืกื‘ื™ื‘ื” ืคื•ืŸ ื“ืขืจ ื“ืขืจืžืึธื ื•ื ื’, ืœืึธืžื™ืจ ื–ืขืŸ ืึท ื‘ื™ื™ืฉืคึผื™ืœ ืคื•ืŸ ืึทืกืขืžื‘ืึทืœื™ื ื’ ืึท ืœื™ื™ื“ื™ืง ื•ื•ื™ื ืงืœื“ื™ืง ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ. ืึทื–ื•ื™, ืœืึธื–ืŸ ืื•ื ื“ื– ืžืึทื›ืŸ ืื•ื ื“ื–ืขืจ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ:

ng n app

ืœื™ื™ื’ PWA ืฆื• ืขืก (ืžื™ืจ ื–ืขื ืขืŸ ืคึผืจืึธื’ืจืขืกื™ื•ื•):

ng add @angular/pwa --project app

ื‘ืฉืขืช ืึท ืžื™ืœื™ืึธืŸ ื ืคึผื ืคึผืึทืงืึทื“ื–ืฉืึทื– ื–ืขื ืขืŸ ื“ืึทื•ื ืœืึธื•ื“ื™ื“, ืœืึธื–ืŸ ืื•ื ื“ื– ืจืขื›ืขื ืขืŸ ืื•ื™ืก ื•ื•ื™ ื“ื™ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ ืึทืจื‘ืขื˜. ื“ืึธืงืขืจ ื’ื™ื˜ ื“ื™ ืคื™ื™ื™ืงื™ื™ื˜ ืฆื• ืคึผืขืงืœ ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื– ืื•ืŸ ืœื•ื™ืคืŸ ื–ื™ื™ ืื™ืŸ ืึทืŸ ืืคื’ืขื–ื•ื ื“ืขืจื˜ ืกื•ื•ื™ื•ื•ืข ื’ืขืจื•ืคืŸ ืึท ืงืึทื ื˜ื™ื™ื ืขืจ. ื“ืึทื ืง ืฆื• ืืคื’ืขื–ื•ื ื“ืขืจื˜ืงื™ื™ื˜, ืื™ืจ ืงืขื ืขืŸ ืœื•ื™ืคืŸ ืคื™ืœืข ืงืึทื ื˜ื™ื™ื ืขืจื– ืกื™ื™ืžืึทืœื˜ื™ื™ื ื™ืึทืกืœื™ ืื•ื™ืฃ ืื™ื™ืŸ ืกืขืจื•ื•ืขืจ. ืงืึทื ื˜ื™ื™ื ืขืจื– ื–ืขื ืขืŸ ืคื™ืœ ืœื™ื™ื˜ืขืจ ื•ื•ื™ ื•ื•ื™ืจื˜ื•ืึทืœ ืžืืฉื™ื ืขืŸ ื•ื•ื™ื™ึทืœ ื–ื™ื™ ืœื•ื™ืคืŸ ื’ืœื™ื™ึทืš ืื•ื™ืฃ ื“ื™ ืกื™ืกื˜ืขื ืงืขืจืŸ. ืฆื• ืœื•ื™ืคืŸ ืึท ืงืึทื ื˜ื™ื™ื ืขืจ ืžื™ื˜ ืื•ื ื“ื–ืขืจ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ, ืžื™ืจ ืขืจืฉื˜ืขืจ ื“ืึทืจืคึฟืŸ ืฆื• ืฉืึทืคึฟืŸ ืึท ื‘ื™ืœื“ ืื™ืŸ ื•ื•ืึธืก ืžื™ืจ ืคึผืึทืงืŸ ืึทืœืฅ ื•ื•ืึธืก ืื™ื– ื ื™ื™ื˜ื™ืง ืคึฟืึทืจ ืื•ื ื“ื–ืขืจ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืฆื• ืœื•ื™ืคืŸ. ื™ืกืขื ืฉืึทืœื™, ืึท ื‘ื™ืœื“ ืื™ื– ืึท ืงืึธืคึผื™ืข ืคื•ืŸ โ€‹โ€‹ื“ื™ ื˜ืขืงืข ืกื™ืกื˜ืขื. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ื ืขืžืขืŸ ื“ื™ 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 .

ืื•ื™ื‘ ื“ื™ ืกื•ื•ื™ื•ื•ืข ืคึฟืึทืจ ื‘ื ื™ืŸ ื‘ื™ืœื“ืขืจ ืื™ื– ืงืึทื ืคื™ื’ื™ืขืจื“ ืจื™ื›ื˜ื™ืง (ืžืขืจ ืื•ื™ืฃ ื“ืขื ืื•ื ื˜ืŸ), ื•ื•ืขืŸ ื“ื™ ื‘ื•ื™ืขืŸ ืกื˜ืึทืจืฅ, ื“ืึธืงืขืจ ื•ื•ืขื˜ ืฉื•ื™ืŸ ื”ืึธื‘ืŸ ืึท ื‘ื™ื ื˜ืœ ืคื•ืŸ ืงืึทื˜ืฉืขืก ืื•ื™ืฃ ื‘ืจืขื˜. ืื•ื ื“ื–ืขืจ ืึทืจื‘ืขื˜ ืื™ื– ืฆื• ืœืขืจื ืขืŸ ื•ื•ื™ ืฆื• ื ื•ืฆืŸ ื“ื™ ืงืึทืฉ ืึทื–ื•ื™ ืึทื– ื“ื™ ื‘ื•ื™ืขืŸ ื’ื™ื™ื˜ ื•ื•ื™ ื’ืขืฉื•ื•ื™ื ื“ ื•ื•ื™ ืžืขื’ืœืขืš. ื–ื™ื ื˜ ืžื™ืจ ื™ื‘ืขืจื ืขืžืขืŸ ืึทื– ืึท ื‘ื•ื™ืขืŸ ืึธืŸ ืึท ืงืึทืฉ ื›ืึทืคึผืึทื ื– ื‘ืœื•ื™ื– ืึทืžืึธืœ - ื“ืขืจ ืขืจืฉื˜ืขืจ ืžืึธืœ - ืžื™ืจ ืงืขื ืขืŸ ื“ืขืจื™ื‘ืขืจ ืื™ื’ื ืึธืจื™ืจืŸ ื•ื•ื™ ืคึผืึทืžืขืœืขืš ื“ื™ ืขืจืฉื˜ืขืจ ืžืึธืœ ืื™ื– ื’ืขื•ื•ืขืŸ. ืื™ืŸ ื˜ืขืกืฅ, ื“ื™ ืจื’ืข ืœื•ื™ืคืŸ ืคื•ืŸ ื“ื™ ื‘ื•ื™ืขืŸ ืื™ื– ื•ื•ื™ื›ื˜ื™ืง ืคึฟืึทืจ ืื•ื ื“ื–, ื•ื•ืขืŸ ื“ื™ ืงืึทื˜ืฉืขืก ื–ืขื ืขืŸ ืฉื•ื™ืŸ ื•ื•ืึธืจืžื“ ืื•ืŸ ืžื™ืจ ื–ืขื ืขืŸ ื’ืจื™ื™ื˜ ืฆื• ื‘ืึทืงืŸ ืื•ื ื“ื–ืขืจ ืฉื˜ื™ืงืœ. ืึธื‘ืขืจ, ืขื˜ืœืขื›ืข ืขืฆื•ืช ื•ื•ืขื˜ ืื•ื™ืš ื•ื•ื™ืจืงืŸ ื“ืขืจ ืขืจืฉื˜ืขืจ ื‘ื•ื™ืขืŸ.

ืœืึธืžื™ืจ ืฉื˜ืขืœืŸ ื“ื™ ื“ืึธืงืงืขืจืคื™ืœืข ื“ื™ืกืงืจื™ื™ื‘ื“ ืื•ื™ื‘ืŸ ืื™ืŸ ื“ื™ ืคึผืจื•ื™ืขืงื˜ ื˜ืขืงืข ืื•ืŸ ืึธื ื”ื™ื™ื‘ืŸ ื“ืขื ื‘ื•ื™ืขืŸ. ืึทืœืข ืœื™ืกื˜ื™ื ื’ืก ื–ืขื ืขืŸ ืงืึทื ื“ืขื ืกื˜ ืคึฟืึทืจ ื™ื– ืคื•ืŸ ืœื™ื™ืขื ืขืŸ.

$ 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. ื“ืขืจ ื‘ื•ื™ืขืŸ ืงืึธื ื˜ืขืงืกื˜ ืื™ื– ืกืคึผืขืกื™ืคื™ืขื“ ื•ื•ื™ ื“ื™ ืœืขืฆื˜ืข ืึทืจื’ื•ืžืขื ื˜ ืฆื• ื“ื™ ื‘ื•ื™ืขืŸ ื‘ืึทืคึฟืขืœ. ืื™ืŸ ืื•ื ื“ื–ืขืจ ืคืึทืœ, ื“ืึธืก ืื™ื– ื“ื™ ืงืจืึทื ื˜ ื•ื•ืขื’ื•ื•ื™ื™ึทื–ืขืจ - ".", - ืื•ืŸ ื“ืึธืงืขืจ ื“ืจืึทื’ืก ืึทืœืฅ ื•ื•ืึธืก ืžื™ืจ ื”ืึธื‘ืŸ ืื™ืŸ ื“ืขื ื˜ืขืงืข. 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 ืื™ืŸ Dockerfile. ืื™ืŸ ืื•ื ื“ื–ืขืจ ืคืึทืœ, ืžื™ืจ ื ื•ืฆืŸ ืึท ื•ื‘ื•ื ื˜ื•-ื‘ืื–ื™ืจื˜ ื‘ื™ืœื“ ื•ื•ืึธืก ืฉื•ื™ืŸ ื”ืื˜ ื ืึธื“ืขื“ื–ืฉืก ืื™ื ืกื˜ืึทืœื™ืจืŸ. ืื•ืŸ ืขืก ื•ื•ื™ื™ื– ...

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

... ื›ึผืžืขื˜ ืึท ื’ื™ื’ืื‘ื™ื™ื˜. ืื™ืจ ืงืขื ืขืŸ ื‘ืื˜ื™ื™ื˜ื™ืง ืจืขื“ื•ืฆื™ืจืŸ ื“ื™ ื‘ืึทื ื“ ื“ื•ืจืš ื ื™ืฆืŸ ืึท ื‘ื™ืœื“ ื‘ืื–ื™ืจื˜ ืื•ื™ืฃ ืึทืœืคึผื™ื™ืŸ ืœื™ื ื•ืงืก. ืึทืœืคึผื™ื™ืŸ ืื™ื– ืึท ื–ื™ื™ืขืจ ืงืœื™ื™ืŸ ืœื™ื ื•ืงืก. ื“ื™ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ ืคึฟืึทืจ ื ืึธื“ืขื“ื–ืฉืก ื‘ืื–ื™ืจื˜ ืื•ื™ืฃ ืึทืœืคึผื™ื™ืŸ ื•ื•ื™ื™ื– ื‘ืœื•ื™ื– 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

ืžื™ืจ ื”ืึธื‘ืŸ ืฆื• ื™ื ืกื˜ืึทืœื™ืจืŸ ืขื˜ืœืขื›ืข ื˜ื™ื ื’ื– ื•ื•ืึธืก ื–ืขื ืขืŸ ื ื™ื™ื˜ื™ืง ืฆื• ื‘ื•ื™ืขืŸ ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ. ื™ืึธ, ืึทื ื’ื•ืœืึทืจ ื˜ื•ื˜ ื ื™ืฉื˜ ื‘ื•ื™ืขืŸ ืึธืŸ ืคึผื™ื˜ื”ืึธืŸ ยฏ (ยฐ _ ืึธ) / ยฏ

ืึธื‘ืขืจ ื“ื™ ื‘ื™ืœื“ ื’ืจื™ื™ืก ืื™ื– ื’ืขืคืืœืŸ ืฆื• 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. ืื™ืŸ ื“ืขื ืคืึทืœ, ื“ื™ ื˜ืขืงืขืก ืขืคืขืก ื“ืึทืจืคึฟืŸ ืฆื• ื–ื™ื™ืŸ ื’ืขื’ืขื‘ืŸ ืึทืจื•ื™ืก. ืื™ืจ ืงืขื ืขืŸ ืœื•ื™ืคืŸ ืขื˜ืœืขื›ืข ื”ื˜ื˜ืคึผ ืกืขืจื•ื•ืขืจ ืื•ื™ืฃ ื ืึธื“ืขื“ื–ืฉืก. ืึธื‘ืขืจ ืžื™ืจ ื•ื•ืขืœืŸ ืžืึทื›ืŸ ืขืก ื’ืจื™ื ื’ืขืจ. ื˜ืจืขืคืŸ ืึท ืจื•ืกื™ืฉ ื•ื•ืึธืจื˜ ื•ื•ืึธืก ื”ืื˜ ืคื™ืจ ืื•ืชื™ื•ืช "ื™". ืจืขื›ื˜! ื™ื ื–ืฉื™ื ื™ืงืกื™. ืœืึธืžื™ืจ ื ืขืžืขืŸ ืึท ื‘ื™ืœื“ ืžื™ื˜ 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/ ืื•ืŸ ืžื™ืจ ื–ืขืŸ ืื•ื ื“ื–ืขืจ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ. ืึทืœืฅ ืึทืจื‘ืขื˜!

ืขื˜ืœืขื›ืข ืขืฆื•ืช ืื•ื™ืฃ ื•ื•ื™ ืฆื• ืคืึทืจื’ื™ื›ืขืจืŸ ื“ื™ ื‘ื™ืœื“ ืคื•ืŸ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ืขืจ. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืึทืจื•ื™ืฃ ืฆื• 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 ืก. ืคืืจื•ื•ืืก ืจื™ื™ื ืกื˜ืึทืœ ื“ื™ืคึผืขื ื“ืึทื ืกื™ื– ื™ืขื“ืขืจ ืžืึธืœ ืื•ื™ื‘ ื–ื™ื™ ื˜ื•ื™ืฉืŸ ื–ื™ื™ืขืจ ืจืึทืจืขืœื™? ืœืืžื™ืจ ืื•ื™ืกืจืขื›ืขื ืขืŸ ืคืืจื•ื•ืืก ื–ื™ื™ ื–ืขื ืขืŸ ื ื™ืฉื˜ ื’ืขื›ืืคื˜ ื’ืขื•ื•ืืจืŸ. ื“ื™ ืคื•ื ื˜ ืื™ื– ืึทื– ื“ืึธืงืขืจ ื•ื•ืขื˜ ืงืึธื ื˜ืจืึธืœื™ืจืŸ ืฉื™ื›ื˜ืข ื“ื•ืจืš ืฉื™ื›ื˜ืข ืฆื• ื–ืขืŸ ืื•ื™ื‘ ื“ื™ ื‘ืึทืคึฟืขืœ ืื•ืŸ ื“ื™ ื˜ืขืงืขืก ืคึฟืึทืจื‘ื•ื ื“ืŸ ืžื™ื˜ ืื™ื ื”ืึธื‘ืŸ ื’ืขื‘ื™ื˜ืŸ. ืื™ืŸ ื“ืขืจ ืคืขืจื˜ ืฉืจื™ื˜, ืžื™ืจ ื ืึธื›ืžืึทื›ืŸ ืึทืœืข ื“ื™ ื˜ืขืงืขืก ืคื•ืŸ ืื•ื ื“ื–ืขืจ ืคึผืจื•ื™ืขืงื˜, ืื•ืŸ ืฆื•ื•ื™ืฉืŸ ื–ื™ื™, ืคื•ืŸ ืงื•ืจืก, ืขืก ื–ืขื ืขืŸ ืขื ื“ืขืจื•ื ื’ืขืŸ, ืึทื–ื•ื™ ื“ืึธืงืขืจ ื ื™ื˜ ื‘ืœื•ื™ื– ื ืขืžืขืŸ ื“ืขื ืฉื™ื›ื˜ืข ืคื•ืŸ โ€‹โ€‹ื“ื™ ืงืึทืฉ, ืึธื‘ืขืจ ืื•ื™ืš ืึทืœืข ื“ื™ ืคืืœื’ืขื ื“ืข! ืœืึธืžื™ืจ ืžืึทื›ืŸ ืขื˜ืœืขื›ืข ืงืœื™ื™ืŸ ืขื ื“ืขืจื•ื ื’ืขืŸ ืฆื• ื“ื™ 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 ืžื™ื ื•ื˜ - ืคื™ืœ ื‘ืขืกืขืจ! ื“ื™ ืจื™ื›ื˜ื™ืง ืกื“ืจ ืคื•ืŸ ืœื™ื™ึทืขืจืก ืื™ื– ื•ื•ื™ื›ื˜ื™ืง: ืขืจืฉื˜ืขืจ ืžื™ืจ ื ืึธื›ืžืึทื›ืŸ ื•ื•ืึธืก ื˜ื•ื˜ ื ื™ืฉื˜ ื˜ื•ื™ืฉืŸ, ื“ืขืžืึธืœื˜ ื•ื•ืึธืก ืขื ื“ืขืจื•ื ื’ืขืŸ ืจืึทืจืขืœื™, ืื•ืŸ ืœืขืกืึธืฃ ื•ื•ืึธืก ืขื ื“ืขืจื•ื ื’ืขืŸ ืึธืคื˜.

ื•ื•ื™ื™ึทื˜ืขืจ, ืึท ื‘ื™ืกืœ ื•ื•ืขืจื˜ืขืจ ื•ื•ืขื’ืŸ ืึทืกืขืžื‘ืึทืœื™ื ื’ ื‘ื™ืœื“ืขืจ ืื™ืŸ ืกื™ / ืกื™ ืกื™ืกื˜ืขืžืขืŸ.

ื ื™ืฆืŸ ืคืจื™ื™ึทืขืจื“ื™ืง ื‘ื™ืœื“ืขืจ ืคึฟืึทืจ ืงืึทืฉ

ืื•ื™ื‘ ืžื™ืจ ื ื•ืฆืŸ ืึท ืžื™ืŸ ืคื•ืŸ ืกืึทืึทืก ืœื™ื™ื–ื•ื ื’ ืคึฟืึทืจ ื“ื™ ื‘ื•ื™ืขืŸ, ื“ื™ ื”ื™ื’ืข ื“ืึธืงืงืขืจ ืงืึทืฉ ืงืขืŸ ื–ื™ื™ืŸ ืจื™ื™ืŸ ืื•ืŸ ืคืจื™ืฉ. ืฆื• ื’ืขื‘ืŸ ื“ืขื ื“ืึธืงืงืขืจ ืึท ืคึผืœืึทืฅ ืฆื• ื‘ืึทืงื•ืžืขืŸ ื“ื™ ื‘ื™ื™ืงื˜ ืœื™ื™ึทืขืจืก, ื’ืขื‘ืŸ ืื™ื ื“ื™ ืคืจื™ืขืจื“ื™ืงืข ื’ืขื‘ื•ื™ื˜ ื‘ื™ืœื“.

ืœืึธืžื™ืจ ื ืขืžืขืŸ ืึท ื‘ื™ื™ืฉืคึผื™ืœ ืคื•ืŸ ื‘ื•ื™ืขืŸ ืื•ื ื“ื–ืขืจ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืื™ืŸ GitHub ืึทืงืฉืึทื ื–. ืžื™ืจ ื ื•ืฆืŸ ื“ืขื ืงืึธื ืคื™ื’ื•ืจืึทื˜ื™ืึธืŸ

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 ืกืขืงื•ื ื“ืขืก:

ืขื˜ืœืขื›ืข ืขืฆื•ืช ืื•ื™ืฃ ื•ื•ื™ ืฆื• ืคืึทืจื’ื™ื›ืขืจืŸ ื“ื™ ื‘ื™ืœื“ ืคื•ืŸ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ืขืจ. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืึทืจื•ื™ืฃ ืฆื• 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 ื•ื•ืขื˜ ื ื™ืฉื˜ ืงืขื ืขืŸ ืฆื• ื’ืขืคึฟื™ื ืขืŸ ื’ืจื™ื™ื˜ ืœื™ื™ึทืขืจืก ืฆื• ื‘ื•ื™ืขืŸ ื“ื™ ื‘ื™ืœื“ ืžื™ื˜ ื ืึธื“ืขื“ื–ืฉืก (ื‘ื™ืœื“ืขืจ ื‘ื™ื ืข). ืื™ืŸ ืกื“ืจ ืฆื• ืกืึธืœื•ื•ืข ื“ืขื ืคึผืจืึธื‘ืœืขื, ืึท ื™ื ื˜ืขืจืžื™ื“ื™ื™ื˜ ื‘ื™ืœื“ ืื™ื– ื‘ืืฉืืคืŸ $IMAGE_NAME-builder-stage ืื•ืŸ ืื™ื– ืคึผื•ืฉื˜ ืฆื• GitHub ืคึผืึทืงื™ื“ื–ืฉื™ื– ืึทื–ื•ื™ ืึทื– ืขืก ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขื•ื•ื™ื™ื ื˜ ืื™ืŸ ืึท ืกืึทื‘ืกืึทืงื•ื•ืึทื ื˜ ื‘ื•ื™ืขืŸ ื•ื•ื™ ืึท ืงืึทืฉ ืžืงื•ืจ.

ืขื˜ืœืขื›ืข ืขืฆื•ืช ืื•ื™ืฃ ื•ื•ื™ ืฆื• ืคืึทืจื’ื™ื›ืขืจืŸ ื“ื™ ื‘ื™ืœื“ ืคื•ืŸ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ืขืจ. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืึทืจื•ื™ืฃ ืฆื• 30 ืกืขืงื•ื ื“ืขืก

ื“ื™ ื’ืึทื ืฅ ืคึฟืึทืจื–ืึทืžืœื•ื ื’ ืฆื™ื™ื˜ ืื™ื– ืจื™ื“ื•ืกื˜ ืฆื• ืื™ื™ืŸ ืื•ืŸ ืึท ื”ืึทืœื‘ ืžื™ื ื•ื˜. ื ื”ืืœื‘ืข ืžื™ื ื•ื˜ ื•ื•ืขืจื˜ ืคืืจื‘ืจืื›ื˜ ืฆื• ืืจื•ื™ืกืฆื™ืขืŸ ืคืจื™ืขืจื“ื™ื’ืข ื‘ื™ืœื“ืขืจ.

ืคึผืจืขื™ืžืึทื’ื™ื ื’

ืืŸ ืื ื“ืขืจ ื•ื•ืขื’ ืฆื• ืกืึธืœื•ื•ืข ื“ื™ ืคึผืจืึธื‘ืœืขื ืคื•ืŸ ืึท ืจื™ื™ืŸ ื“ืึธืงืงืขืจ ืงืึทืฉ ืื™ื– ืฆื• ืึทืจื™ื‘ืขืจืคื™ืจืŸ ืขื˜ืœืขื›ืข ืคื•ืŸ โ€‹โ€‹ื“ื™ ืœื™ื™ึทืขืจืก ืื™ืŸ ืืŸ ืื ื“ืขืจ Dockerfile, ื‘ื•ื™ืขืŸ ืขืก ืกืขืคึผืขืจืึทื˜ืœื™, ืฉื˜ื•ืคึผืŸ ืขืก ืื™ืŸ ื“ื™ ืงืึทื ื˜ื™ื™ื ืขืจ ืจืขื’ื™ืกื˜ืจื™ ืื•ืŸ ื ื•ืฆืŸ ืขืก ื•ื•ื™ ืึท ืคืึธื˜ืขืจ.

ืžื™ืจ ืžืึทื›ืŸ ืื•ื ื“ื–ืขืจ ืื™ื™ื’ืขื ืข ื ืึธื“ืขื“ื–ืฉืก ื‘ื™ืœื“ ืฆื• ื‘ื•ื™ืขืŸ ืึทืŸ ืึทื ื’ื•ืœืึทืจ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ. ืฉืึทืคึฟืŸ 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
...

ืื™ืŸ ืื•ื ื“ื–ืขืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ื“ื™ ื‘ื•ื™ืขืŸ ืฆื™ื™ื˜ ืื™ื– ื ื™ืฉื˜ ืคืึทืจืงืœืขื ืขืจืŸ, ืึธื‘ืขืจ ืคืึทืจ-ื’ืขื‘ื•ื™ื˜ ื‘ื™ืœื“ืขืจ ืงืขื ืขืŸ ื–ื™ื™ืŸ ื ื•ืฆื™ืง ืื•ื™ื‘ ืื™ืจ ื”ืึธื‘ืŸ ืคื™ืœืข ืคึผืจืึทื“ื–ืฉืขืงืก ืื•ืŸ ืื™ืจ ืžื•ื–ืŸ ื™ื ืกื˜ืึทืœื™ืจืŸ ื“ื™ ื–ืขืœื‘ืข ื“ื™ืคึผืขื ื“ืึทื ืกื™ื– ืื™ืŸ ื™ืขื“ืขืจ ืคื•ืŸ ื–ื™ื™.

ืขื˜ืœืขื›ืข ืขืฆื•ืช ืื•ื™ืฃ ื•ื•ื™ ืฆื• ืคืึทืจื’ื™ื›ืขืจืŸ ื“ื™ ื‘ื™ืœื“ ืคื•ืŸ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ืขืจ. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืึทืจื•ื™ืฃ ืฆื• 30 ืกืขืงื•ื ื“ืขืก

ืžื™ืจ ื”ืึธื‘ืŸ ื’ืขืงื•ืงื˜ ืื•ื™ืฃ ืขื˜ืœืขื›ืข ืžืขื˜ื”ืึธื“ืก ืฆื• ืคืึทืจื’ื™ื›ืขืจืŸ ื“ื™ ื‘ื•ื™ืขืŸ ืคื•ืŸ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ืขืจ. ืื•ื™ื‘ ืื™ืจ ื•ื•ื™ืœืŸ ื“ื™ ื“ื™ืคึผืœื•ื™ืžืึทื ื˜ ืฆื• ื’ื™ื™ืŸ ื’ืขืฉื•ื•ื™ื ื“, ืคึผืจื•ื‘ื™ืจืŸ ืฆื• ื ื•ืฆืŸ ื“ืขื ืื™ืŸ ื“ื™ื™ืŸ ืคึผืจื•ื™ืขืงื˜:

  • ืจื™ื“ื•ืกื™ื ื’ ืงืึธื ื˜ืขืงืกื˜;
  • ื ื•ืฆืŸ ืคื•ืŸ ืงืœื™ื™ืŸ ืคืึธื˜ืขืจ ื‘ื™ืœื“ืขืจ;
  • ืžื•ืœื˜ื™-ืกื˜ืึทื’ืข ืคึฟืึทืจื–ืึทืžืœื•ื ื’;
  • ื˜ืฉืึทื ื’ื™ื ื’ ื“ื™ ืกื“ืจ ืคื•ืŸ ื™ื ืกื˜ืจืึทืงืฉืึทื ื– ืื™ืŸ ื“ื™ Dockerfile ืฆื• ืžืึทื›ืŸ ืขืคืขืงื˜ื™ื•ื• ื ื•ืฆืŸ ืคื•ืŸ ื“ื™ ืงืึทืฉ;
  • ื‘ืึทืฉื˜ืขื˜ื™ืงืŸ ืึท ืงืึทืฉ ืื™ืŸ ืกื™ / ืกื™ ืกื™ืกื˜ืขืžืขืŸ;
  • ืคึผืจื™ืœื™ืžืึทื ืขืจื™ ืฉืึทืคื•ื ื’ ืคื•ืŸ ื‘ื™ืœื“ืขืจ.

ืื™ืš ื”ืึธืคึฟืŸ ืึทื– ื“ื™ ื‘ื™ื™ืฉืคึผื™ืœ ื•ื•ืขื˜ ืžืึทื›ืŸ ืขืก ืงืœื™ืจืขืจ ื•ื•ื™ Docker ืึทืจื‘ืขื˜, ืื•ืŸ ืื™ืจ ื•ื•ืขื˜ ืงืขื ืขืŸ ืฆื• ืึธืคึผื˜ื™ืžืึทืœืœื™ ืงืึทื ืคื™ื’ื™ืขืจ ื“ื™ื™ืŸ ื“ื™ืคึผืœื•ื™ืžืึทื ื˜. ืฆื• ืฉืคึผื™ืœืŸ ืžื™ื˜ ื“ื™ ื‘ื™ื™ืฉืคื™ืœืŸ ืคื•ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ, ืึท ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™ ืื™ื– ื‘ืืฉืืคืŸ ื’ืขื•ื•ืืจืŸ https://github.com/devopsprodigy/test-docker-build.

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’