เบฎเบนเบšเบžเบฒเบš Docker เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เปเบˆเบเบขเบฒเบเบ‚เบญเบ‡ Single Page Application

เบ„เปเบฒเบฎเป‰เบญเบ‡เบชเบฐเบซเบกเบฑเบเบซเบ™เป‰เบฒเบ”เบฝเบง (SPA) เปเบกเปˆเบ™เบŠเบธเบ”เบ‚เบญเบ‡เป„เบŸเบฅเปŒ JavaScript เปเบฅเบฐ HTML เบ„เบปเบ‡เบ—เบตเปˆ, เป€เบŠเบฑเปˆเบ™เบ”เบฝเบงเบเบฑเบ™เบเบฑเบšเบฎเบนเบšเบžเบฒเบšเปเบฅเบฐเบŠเบฑเบšเบžเบฐเบเบฒเบเบญเบ™เบญเบทเปˆเบ™เป†. เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒเบžเบงเบเป€เบ‚เบปเบฒเบšเปเปˆเบ›เปˆเบฝเบ™เปเบ›เบ‡เปเบšเบšเป€เบ„เบทเปˆเบญเบ™เป„เบซเบง, เบเบฒเบ™เป€เบœเบตเบเปเบœเปˆเบžเบงเบเบกเบฑเบ™เบญเบญเบ™เป„เบฅเบ™เปŒเปเบกเปˆเบ™เบ‡เปˆเบฒเบเบซเบผเบฒเบ. เบกเบตเบˆเปเบฒเบ™เบงเบ™เบซเบฅเบฒเบเบ‚เบญเบ‡เบฅเบฒเบ„เบฒเบ–เบทเบเปเบฅเบฐเปเบกเป‰เบเบฐเบ—เบฑเป‰เบ‡เบšเปเบฅเบดเบเบฒเบ™เบŸเบฃเบตเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ™เบตเป‰, เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เบ”เป‰เบงเบเบซเบ™เป‰เบฒ GitHub เบ‡เปˆเบฒเบเบ”เบฒเบ (เปเบฅเบฐเบชเปเบฒเบฅเบฑเบšเบšเบฒเบ‡เบ„เบปเบ™เป€เบ–เบดเบ‡เปเบกเปˆเบ™เบงเปˆเบฒเบกเบต narod.ru) เปเบฅเบฐเบชเบดเป‰เบ™เบชเบธเบ”เบ”เป‰เบงเบ CDN เป€เบŠเบฑเปˆเบ™ Amazon S3. เบขเปˆเบฒเบ‡เปƒเบ”เบเปเบ•เบฒเบก, เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบ•เป‰เบญเบ‡เบเบฒเบ™เบšเบฒเบ‡เบชเบดเปˆเบ‡เบšเบฒเบ‡เบขเปˆเบฒเบ‡เบญเบทเปˆเบ™.

เบ‚เป‰เบญเบเบ•เป‰เบญเบ‡เบเบฒเบ™เบฎเบนเบšเบžเบฒเบš Docker เบเบฑเบš SPA เป€เบžเบทเปˆเบญเปƒเบซเป‰เบกเบฑเบ™เบชเบฒเบกเบฒเบ”เป€เบ›เบตเบ”เบ•เบปเบงเป„เบ”เป‰เบขเปˆเบฒเบ‡เบ‡เปˆเบฒเบเบ”เบฒเบเบ—เบฑเบ‡เปƒเบ™เบเบฒเบ™เบœเบฐเบฅเบดเบ”เป€เบ›เบฑเบ™เบชเปˆเบงเบ™เบซเบ™เบถเปˆเบ‡เบ‚เบญเบ‡เบเบธเปˆเบก Kubernetes, เปเบฅเบฐเบขเบนเปˆเปƒเบ™เป€เบ„เบทเปˆเบญเบ‡เบ‚เบญเบ‡เบ™เบฑเบเบžเบฑเบ”เบ—เบฐเบ™เบฒ back-end เบœเบนเป‰เบ—เบตเปˆเบšเปเปˆเบฎเบนเป‰เบงเปˆเบฒ SPA เปเบกเปˆเบ™เบซเบเบฑเบ‡.

เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเป„เบ”เป‰เบเปเบฒเบ™เบปเบ”เบ„เบงเบฒเบกเบ•เป‰เบญเบ‡เบเบฒเบ™เบฎเบนเบšเบžเบฒเบšเบ•เปเปˆเป„เบ›เบ™เบตเป‰เบชเปเบฒเบฅเบฑเบšเบ•เบปเบ™เป€เบญเบ‡:

  • เบ„เบงเบฒเบกเบ‡เปˆเบฒเบเบ‚เบญเบ‡เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰ (เปเบ•เปˆเบšเปเปˆเปเบกเปˆเบ™เบเบฒเบ™เบ›เบฐเบเบญเบš);
  • เบ‚เบฐเบซเบ™เบฒเบ”เบ•เปเบฒเปˆเบชเบธเบ”เบ—เบตเปˆเบ—เบฑเบ‡เปƒเบ™เปเบ‡เปˆเบ‚เบญเบ‡เปเบœเปˆเบ™เปเบฅเบฐ RAM;
  • เบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเป‚เบ”เบเบœเปˆเบฒเบ™เบ•เบปเบงเปเบ›เบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบกเป€เบžเบทเปˆเบญเปƒเบซเป‰เบฎเบนเบšเบžเบฒเบšเบชเบฒเบกเบฒเบ”เบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เปƒเบ™เบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบกเบ—เบตเปˆเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™;
  • เบเบฒเบ™เปเบˆเบเบขเบฒเบเป„เบŸเบฅเปŒเบ—เบตเปˆเบกเบตเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเบซเบผเบฒเบเบ—เบตเปˆเบชเบธเบ”.

เบกเบทเป‰เบ™เบตเป‰เบ‚เป‰เบญเบเบˆเบฐเบšเบญเบเป€เบˆเบปเป‰เบฒเบงเปˆเบฒ:

  • gut nginx;
  • เบชเป‰เบฒเบ‡ brotli เบˆเบฒเบเปเบซเบผเปˆเบ‡;
  • เบชเบญเบ™เป„เบŸเบฅเปŒเบชเบฐเบ–เบดเบ”เป€เบžเบทเปˆเบญเป€เบ‚เบปเป‰เบฒเปƒเบˆเบ•เบปเบงเปเบ›เบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบก;
  • เปเบฅเบฐเปเบ™เปˆเบ™เบญเบ™เบงเบดเบ—เบตเบเบฒเบ™เบ›เบฐเบเบญเบšเบฎเบนเบšเบžเบฒเบš Docker เบˆเบฒเบเบ—เบฑเบ‡เบซเบกเบปเบ”เบ™เบตเป‰.

เบˆเบธเบ”เบ›เบฐเบชเบปเบ‡เบ‚เบญเบ‡เบšเบปเบ”เบ„เบงเบฒเบกเบ™เบตเป‰เปเบกเปˆเบ™เป€เบžเบทเปˆเบญเปเบšเปˆเบ‡เบ›เบฑเบ™เบ›เบฐเบชเบปเบšเบเบฒเบ™เบ‚เบญเบ‡เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเปเบฅเบฐ provoke เบชเบฐเบกเบฒเบŠเบดเบเบŠเบธเบกเบŠเบปเบ™เบ—เบตเปˆเบกเบตเบ›เบฐเบชเบปเบšเบเบฒเบ™เปƒเบ™เบเบฒเบ™เบงเบดเบžเบฒเบเบงเบดเบˆเบฒเบ™เบเบฒเบ™เบเปเปˆเบชเป‰เบฒเบ‡.

เบเบฒเบ™เบชเป‰เบฒเบ‡เบฎเบนเบšเบžเบฒเบšเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ›เบฐเบเบญเบš

เป€เบžเบทเปˆเบญเป€เบฎเบฑเบ”เปƒเบซเป‰เบฎเบนเบšเบžเบฒเบš Docker เบชเบธเบ”เบ—เป‰เบฒเบเบกเบตเบ‚เบฐเบซเบ™เบฒเบ”เบ™เป‰เบญเบ, เบ—เปˆเบฒเบ™เบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เป„เบ”เป‰เบ›เบฐเบ•เบดเบšเบฑเบ”เบ•เบฒเบกเบเบปเบ”เบฅเบฐเบšเบฝเบšเบชเบญเบ‡เบขเปˆเบฒเบ‡: เบ‚เบฑเป‰เบ™เบ•เปˆเปเบฒเบ‚เบญเบ‡เบŠเบฑเป‰เบ™เปเบฅเบฐเบฎเบนเบšเบžเบฒเบšเบžเบทเป‰เบ™เบ–เบฒเบ™เบซเบ™เป‰เบญเบ. เบซเบ™เบถเปˆเบ‡เปƒเบ™เบฎเบนเบšเบžเบฒเบšเบžเบทเป‰เบ™เบ–เบฒเบ™เบ—เบตเปˆเบ™เป‰เบญเบเบ—เบตเปˆเบชเบธเบ”เปเบกเปˆเบ™เบฎเบนเบšเบžเบฒเบš Alpine Linux, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบ‚เป‰เบญเบเบˆเบฐเป€เบฅเบทเบญเบ. เบšเบฒเบ‡เบ„เบปเบ™เบญเบฒเบ”เบˆเบฐเป‚เบ•เป‰เบ–เบฝเบ‡เบงเปˆเบฒ Alpine เบšเปเปˆเป€เบซเบกเบฒเบฐเบชเบปเบกเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบœเบฐเบฅเบดเบ”, เปเบฅเบฐเบžเบงเบเป€เบ‚เบปเบฒเบญเบฒเบ”เบˆเบฐเบ–เบทเบเบ•เป‰เบญเบ‡. เปเบ•เปˆเบชเปˆเบงเบ™เบ•เบปเบง, เบ‚เป‰เบญเบเบšเปเปˆเป€เบ„เบตเบเบกเบตเบšเบฑเบ™เบซเบฒเบเบฑเบšเบฅเบฒเบงเปเบฅเบฐเบšเปเปˆเบกเบตเบเบฒเบ™เป‚เบ•เป‰เบ–เบฝเบ‡เบเบฑเบšเบฅเบฒเบง.

เป€เบžเบทเปˆเบญเปƒเบซเป‰เบกเบตเบŠเบฑเป‰เบ™เบซเบ™เป‰เบญเบ, เบ‚เป‰เบญเบเบˆเบฐเบ›เบฐเบเบญเบšเบฎเบนเบšเบžเบฒเบšเปƒเบ™ 2 เบ‚เบฑเป‰เบ™เบ•เบญเบ™. เบ—เปเบฒเบญเบดเบ”เปเบกเปˆเบ™เบฎเปˆเบฒเบ‡; เบญเบธเบ›เบฐเบเบญเบ™เบŠเปˆเบงเบเปเบฅเบฐเป„เบŸเบฅเปŒเบŠเบปเปˆเบงเบ„เบฒเบงเบ—เบฑเบ‡เบซเบกเบปเบ”เบˆเบฐเบเบฑเบ‡เบ„เบปเบ‡เบขเบนเปˆเปƒเบ™เบกเบฑเบ™. เปเบฅเบฐเปƒเบ™เบ‚เบฑเป‰เบ™เบ•เบญเบ™เบชเบธเบ”เบ—เป‰เบฒเบเบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบˆเบฐเบ‚เบฝเบ™เบžเบฝเบ‡เปเบ•เปˆเบชเบฐเบšเบฑเบšเบชเบธเบ”เบ—เป‰เบฒเบเบ‚เบญเบ‡เบ„เปเบฒเบฎเป‰เบญเบ‡เบชเบฐเบซเบกเบฑเบ.

เปƒเบซเป‰เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เบ”เป‰เบงเบเบฎเบนเบšเบžเบฒเบšเป€เบชเบตเบก.

เป€เบžเบทเปˆเบญเบฅเบงเบšเบฅเบงเบกเบ„เปเบฒเบฎเป‰เบญเบ‡เบชเบฐเบซเบกเบฑเบ SPA, เบ›เบปเบเบเบฐเบ•เบดเปเบฅเป‰เบงเบ—เปˆเบฒเบ™เบ•เป‰เบญเบ‡เบเบฒเบ™ node.js. เบ‚เป‰เบญเบเบˆเบฐเป€เบญเบปเบฒเบฎเบนเบšเบžเบฒเบšเบ—เบตเปˆเป€เบ›เบฑเบ™เบ—เบฒเบ‡เบเบฒเบ™, เป€เบŠเบดเปˆเบ‡เบกเบฒเบžเป‰เบญเบกเบเบฑเบš npm เปเบฅเบฐเบœเบนเป‰เบˆเบฑเบ”เบเบฒเบ™เบŠเบธเบ”เป€เบชเบฑเป‰เบ™เบ”เป‰เบฒเบ. เปƒเบ™เบ™เบฒเบกเบ‚เบญเบ‡เบ‚เป‰เบญเบเป€เบญเบ‡, เบ‚เป‰เบญเบเบˆเบฐเป€เบžเบตเปˆเบก node-gyp, เป€เบŠเบดเปˆเบ‡เบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เบชเป‰เบฒเบ‡เบšเบฒเบ‡เปเบžเบฑเบเป€เบเบฑเบ” npm, เปเบฅเบฐเป€เบ„เบทเปˆเบญเบ‡เบญเบฑเบ” Brotli เบˆเบฒเบ Google, เป€เบŠเบดเปˆเบ‡เบˆเบฐเป€เบ›เบฑเบ™เบ›เบฐเป‚เบซเบเบ”เบ•เปเปˆเบžเบงเบเป€เบฎเบปเบฒเบ•เปเปˆเบกเบฒ.

Dockerfile เบเบฑเบšเบ„เปเบฒเป€เบซเบฑเบ™.

# ะ‘ะฐะทะพะฒั‹ะน ะพะฑั€ะฐะท
FROM node:12-alpine
LABEL maintainer="Aleksey Maydokin <[email protected]>"
ENV BROTLI_VERSION 1.0.7
# ะŸะฐะบะตั‚ั‹, ะบะพั‚ะพั€ั‹ะต ะฝัƒะถะฝั‹, ั‡ั‚ะพะฑั‹ ัะพะฑั€ะฐั‚ัŒ ะธะท ะธัั…ะพะดะฝะธะบะพะฒ Brotli
RUN apk add --no-cache --virtual .build-deps 
        bash 
        gcc 
        libc-dev 
        make 
        linux-headers 
        cmake 
        curl 
    && mkdir -p /usr/src 
    # ะ˜ัั…ะพะดะฝะธะบะธ Brotli ัะบะฐั‡ะธะฒะฐะตะผ ะธะท ะพั„ะธั†ะธะฐะปัŒะฝะพะณะพ ั€ะตะฟะพะทะธั‚ะพั€ะธั
    && curl -LSs https://github.com/google/brotli/archive/v$BROTLI_VERSION.tar.gz | tar xzf - -C /usr/src 
    && cd /usr/src/brotli-$BROTLI_VERSION 
    # ะšะพะผะฟะธะปะธั€ัƒะตะผ Brotli
    && ./configure-cmake --disable-debug && make -j$(getconf _NPROCESSORS_ONLN) && make install 
    # ะ”ะพะฑะฐะฒะปัะตะผ node-gyp
    && yarn global add node-gyp 
    # ะฃะฑะธั€ะฐะตะผ ะทะฐ ัะพะฑะพะน ะผัƒัะพั€
    && apk del .build-deps && yarn cache clean && rm -rf /usr/src

เปเบฅเป‰เบงเบขเบนเปˆเบ—เบตเปˆเบ™เบตเป‰เบ‚เป‰เบญเบเบเปเบฒเบฅเบฑเบ‡เบชเบนเป‰เบเบฑเบ™เบชเปเบฒเบฅเบฑเบš minimalism, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบฎเบนเบšเบžเบฒเบšเป„เบ”เป‰เบ–เบทเบเป€เบญเบปเบฒเปƒเบˆเปƒเบชเปˆเบฎเปˆเบงเบกเบเบฑเบ™เป‚เบ”เบเบ—เบตเบกเบ‡เบฒเบ™เปƒเบซเบเปˆเบซเบ™เบถเปˆเบ‡.

เบฎเบนเบšเบžเบฒเบšเบชเปเบฒเป€เบฅเบฑเบ”เบฎเบนเบšเบชเบฒเบกเบฒเบ”เบžเบปเบšเป„เบ”เป‰เบ—เบตเปˆเบ™เบตเป‰: https://hub.docker.com/r/alexxxnf/spa-builder. เป€เบ–เบดเบ‡เปเบกเปˆเบ™เบงเปˆเบฒเบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเปเบ™เบฐเบ™เปเบฒเปƒเบซเป‰เบšเปเปˆเบญเบตเบ‡เปƒเบชเปˆเบฎเบนเบšเบžเบฒเบšเบ‚เบญเบ‡เบ„เบปเบ™เบญเบทเปˆเบ™เปเบฅเบฐเป€เบเบฑเบšเบเปเบฒเบ‚เปเป‰เบกเบนเบ™เบ‚เบญเบ‡เบ—เปˆเบฒเบ™เป€เบญเบ‡.

nginx

เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ™เปเบฒเปƒเบŠเป‰เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเป€เบงเบฑเบšเป„เบŠเบ•เปŒเปƒเบ”เบซเบ™เบถเปˆเบ‡เป€เบžเบทเปˆเบญเปเบˆเบเบขเบฒเบเป€เบ™เบทเป‰เบญเบซเบฒเบ—เบตเปˆเบชเบฐเบ–เบดเบ”. เบ‚เป‰เบญเบเป€เบ„เบตเบเป€เบฎเบฑเบ”เบงเบฝเบเบเบฑเบš nginx, เบชเบฐเบ™เบฑเป‰เบ™เบ‚เป‰เบญเบเบˆเบฐเปƒเบŠเป‰เบกเบฑเบ™เบ”เบฝเบงเบ™เบตเป‰.

Nginx เบกเบตเบฎเบนเบšเบžเบฒเบš Docker เบขเปˆเบฒเบ‡เป€เบ›เบฑเบ™เบ—เบฒเบ‡เบเบฒเบ™, เปเบ•เปˆเบกเบฑเบ™เบกเบตเป‚เบกเบ”เบนเบ™เบซเบผเบฒเบเป€เบเบตเบ™เป„เบ›เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เปเบˆเบเบขเบฒเบเปเบšเบšเบ„เบปเบ‡เบ—เบตเปˆเบ‡เปˆเบฒเบเบ”เบฒเบ. เบญเบฑเบ™เปƒเบ”เบ—เบตเปˆเบ–เบทเบเบฅเบงเบกเบขเบนเปˆเปƒเบ™เบเบฒเบ™เบˆเบฑเบ”เบชเบปเปˆเบ‡เบชเบฒเบกเบฒเบ”เป€เบซเบฑเบ™เป„เบ”เป‰เป‚เบ”เบเบ—เบตเบกเบ‡เบฒเบ™เบžเบดเป€เบชเบ”เบซเบผเบทเปƒเบ™ Dockerfile เบขเปˆเบฒเบ‡เป€เบ›เบฑเบ™เบ—เบฒเบ‡เบเบฒเบ™.

$ docker run --rm nginx:1-alpine nginx -V

nginx version: nginx/1.17.9
built by gcc 8.3.0 (Alpine 8.3.0) 
built with OpenSSL 1.1.1d  10 Sep 2019
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --with-perl_modules_path=/usr/lib/perl5/vendor_perl --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-Os -fomit-frame-pointer' --with-ld-opt=-Wl,--as-needed

เบ‚เป‰เบญเบเบˆเบฐเปƒเบŠเป‰ Dockerfile เป€เบ›เบฑเบ™เบžเบทเป‰เบ™เบ–เบฒเบ™, เปเบ•เปˆเบ‚เป‰เบญเบเบˆเบฐเบญเบญเบเบˆเบฒเบเบกเบฑเบ™เบžเบฝเบ‡เปเบ•เปˆเบชเบดเปˆเบ‡เบ—เบตเปˆเบˆเปเบฒเป€เบ›เบฑเบ™เป€เบžเบทเปˆเบญเปเบˆเบเบขเบฒเบเป€เบ™เบทเป‰เบญเบซเบฒเบ—เบตเปˆเบชเบฐเบ–เบดเบ”. เบชเบฐเบšเบฑเบšเบ‚เบญเบ‡เบ‚เป‰เบญเบเบˆเบฐเบšเปเปˆเบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เบงเบฝเบเบœเปˆเบฒเบ™ HTTPS, เบˆเบฐเบšเปเปˆเบชเบฐเบซเบ™เบฑเบšเบชเบฐเบซเบ™เบนเบ™เบเบฒเบ™เบญเบฐเบ™เบธเบเบฒเบ”, เปเบฅเบฐเบญเบทเปˆเบ™เป†เบญเบตเบ. เปเบ•เปˆเบชเบฐเบšเบฑเบšเบ‚เบญเบ‡เบ‚เป‰เบญเบเบˆเบฐเบชเบฒเบกเบฒเบ”เปเบˆเบเบขเบฒเบเป„เบŸเบฅเปŒเบ—เบตเปˆเบ–เบทเบเบšเบตเบšเบญเบฑเบ”เบ”เป‰เบงเบ Brotli algorithm, เป€เบŠเบดเปˆเบ‡เบกเบตเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเบซเบผเบฒเบเบเปˆเบงเบฒ gzip เป€เบฅเบฑเบเบ™เป‰เบญเบ. เบžเบงเบโ€‹เป€เบฎเบปเบฒโ€‹เบˆเบฐโ€‹เบšเบตเบšโ€‹เบญเบฑเบ”โ€‹เป„เบŸเบฅโ€‹เปŒโ€‹เบซเบ™เบถเปˆเบ‡โ€‹เบ„เบฑเป‰เบ‡โ€‹, เบšเปเปˆโ€‹เบˆเปเบฒโ€‹เป€เบ›เบฑเบ™โ€‹เบ•เป‰เบญเบ‡โ€‹เป€เบฎเบฑเบ”โ€‹เบชเบดเปˆเบ‡โ€‹เบ™เบตเป‰โ€‹เปƒเบ™โ€‹เบเบฒเบ™โ€‹เบšเบดเบ™โ€‹.

เบ™เบตเป‰เปเบกเปˆเบ™ Dockerfile เบ—เบตเปˆเบ‚เป‰เบญเบเบˆเบปเบšเบฅเบปเบ‡เบ”เป‰เบงเบ. เบ„เปเบฒเป€เบซเบฑเบ™เปƒเบ™เบžเบฒเบชเบฒเบฅเบฑเบ”เป€เบŠเบเปเบกเปˆเบ™เบ‚เบญเบ‡เบ‚เป‰เบญเบ, เปƒเบ™เบžเบฒเบชเบฒเบญเบฑเบ‡เบเบดเบ” - เบˆเบฒเบเบ•เบปเป‰เบ™เบชเบฐเบšเบฑเบš.

dockerfile

# ะ‘ะฐะทะพะฒั‹ะน ะพะฑั€ะฐะท ัะฝะพะฒะฐ Alpine
FROM alpine:3.9
LABEL maintainer="Aleksey Maydokin <[email protected]>"
ENV NGINX_VERSION 1.16.0
ENV NGX_BROTLI_VERSION 0.1.2
ENV BROTLI_VERSION 1.0.7
RUN set -x 
    && addgroup -S nginx 
    && adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx nginx 
# ะฃัั‚ะฐะฝะฐะฒะปะธะฒะฐะตะผ ะฟะฐะบะตั‚ั‹, ะบะพั‚ะพั€ั‹ะต ะฝัƒะถะฝั‹ ั‡ั‚ะพะฑั‹ ัะพะฑั€ะฐั‚ัŒ nginx ะธ ะผะพะดัƒะปัŒ ngx_brotli ะบ ะฝะตะผัƒ
    && apk add --no-cache --virtual .build-deps 
            gcc 
            libc-dev 
            make 
            linux-headers 
            curl 
    && mkdir -p /usr/src 
# ะกะบะฐั‡ะธะฒะฐะตะผ ะธัั…ะพะดะฝะธะบะธ
    && curl -LSs https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz | tar xzf - -C /usr/src 
    && curl -LSs https://github.com/eustas/ngx_brotli/archive/v$NGX_BROTLI_VERSION.tar.gz | tar xzf - -C /usr/src 
    && curl -LSs https://github.com/google/brotli/archive/v$BROTLI_VERSION.tar.gz | tar xzf - -C /usr/src 
    && rm -rf /usr/src/ngx_brotli-$NGX_BROTLI_VERSION/deps/brotli/ 
    && ln -s /usr/src/brotli-$BROTLI_VERSION /usr/src/ngx_brotli-$NGX_BROTLI_VERSION/deps/brotli 
    && cd /usr/src/nginx-$NGINX_VERSION 
    && CNF="
            --prefix=/etc/nginx 
            --sbin-path=/usr/sbin/nginx 
            --modules-path=/usr/lib/nginx/modules 
            --conf-path=/etc/nginx/nginx.conf 
            --error-log-path=/var/log/nginx/error.log 
            --http-log-path=/var/log/nginx/access.log 
            --pid-path=/var/run/nginx.pid 
            --lock-path=/var/run/nginx.lock 
            --http-client-body-temp-path=/var/cache/nginx/client_temp 
            --http-proxy-temp-path=/var/cache/nginx/proxy_temp 
            --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp 
            --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp 
            --http-scgi-temp-path=/var/cache/nginx/scgi_temp 
            --user=nginx 
            --group=nginx 
            --without-http_ssi_module 
            --without-http_userid_module 
            --without-http_access_module 
            --without-http_auth_basic_module 
            --without-http_mirror_module 
            --without-http_autoindex_module 
            --without-http_geo_module 
            --without-http_split_clients_module 
            --without-http_referer_module 
            --without-http_rewrite_module 
            --without-http_proxy_module 
            --without-http_fastcgi_module 
            --without-http_uwsgi_module 
            --without-http_scgi_module 
            --without-http_grpc_module 
            --without-http_memcached_module 
            --without-http_limit_conn_module 
            --without-http_limit_req_module 
            --without-http_empty_gif_module 
            --without-http_browser_module 
            --without-http_upstream_hash_module 
            --without-http_upstream_ip_hash_module 
            --without-http_upstream_least_conn_module 
            --without-http_upstream_keepalive_module 
            --without-http_upstream_zone_module 
            --without-http_gzip_module 
            --with-http_gzip_static_module 
            --with-threads 
            --with-compat 
            --with-file-aio 
            --add-dynamic-module=/usr/src/ngx_brotli-$NGX_BROTLI_VERSION 
    " 
# ะกะพะฑะธั€ะฐะตะผ
    && ./configure $CNF 
    && make -j$(getconf _NPROCESSORS_ONLN) 
    && make install 
    && rm -rf /usr/src/ 
# ะฃะดะฐะปัะตะผ ะดะธะฝะฐะผะธั‡ะตัะบะธะน brotli ะผะพะดัƒะปัŒ, ะพัั‚ะฐะฒะปัั ั‚ะพะปัŒะบะพ ัั‚ะฐั‚ะธั‡ะตัะบะธะน
    && rm /usr/lib/nginx/modules/ngx_http_brotli_filter_module.so 
    && sed -i '$ d' /etc/apk/repositories 
# Bring in gettext so we can get `envsubst`, then throw
# the rest away. To do this, we need to install `gettext`
# then move `envsubst` out of the way so `gettext` can
# be deleted completely, then move `envsubst` back.
    && apk add --no-cache --virtual .gettext gettext 
    && mv /usr/bin/envsubst /tmp/ 
    && runDeps="$( 
        scanelf --needed --nobanner /usr/sbin/nginx /usr/lib/nginx/modules/*.so /tmp/envsubst 
            | awk '{ gsub(/,/, "nso:", $2); print "so:" $2 }' 
            | sort -u 
            | xargs -r apk info --installed 
            | sort -u 
    )" 
    && apk add --no-cache $runDeps 
    && apk del .build-deps 
    && apk del .gettext 
    && mv /tmp/envsubst /usr/local/bin/ 
# Bring in tzdata so users could set the timezones through the environment
# variables
    && apk add --no-cache tzdata 
# forward request and error logs to docker log collector
    && ln -sf /dev/stdout /var/log/nginx/access.log 
    && ln -sf /dev/stderr /var/log/nginx/error.log
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
STOPSIGNAL SIGTERM
CMD ["nginx", "-g", "daemon off;"]

เบ‚เป‰เบญเบเบˆเบฐเปเบเป‰เป„เบ‚ nginx.conf เบ—เบฑเบ™เบ—เบตเป€เบžเบทเปˆเบญเปƒเบซเป‰ gzip เปเบฅเบฐ brotli เบ–เบทเบเป€เบ›เบตเบ”เปƒเบŠเป‰เป‚เบ”เบเบ„เปˆเบฒเป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™. เบ‚เป‰เบญเบเบเบฑเบ‡เบˆเบฐเบฅเบงเบกเป€เบญเบปเบฒเบชเปˆเบงเบ™เบซเบปเบงเบ‚เบญเบ‡เบ–เบฒเบ™เบ„เบงเบฒเบกเบˆเปเบฒ, เป€เบžเบฒเบฐเบงเปˆเบฒเบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบšเปเปˆเป€เบ„เบตเบเบ›เปˆเบฝเบ™เปเบ›เบ‡เปเบšเบšเบ„เบปเบ‡เบ—เบตเปˆ. เปเบฅเบฐเบเบฒเบ™เบชเปเบฒเบžเบฑเบ”เบชเบธเบ”เบ—เป‰เบฒเบเบˆเบฐเป€เบ›เบฑเบ™เบเบฒเบ™เบ›เปˆเบฝเบ™เป€เบชเบฑเป‰เบ™เบ—เบฒเบ‡เบ—เบฑเบ‡เบซเบกเบปเบ” 404 เบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เป index.html, เบ™เบตเป‰เปเบกเปˆเบ™เบกเบตเบ„เบงเบฒเบกเบˆเปเบฒเป€เบ›เบฑเบ™เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ™เปเบฒเบ—เบฒเบ‡เปƒเบ™ SPA.

nginx.conf

user nginx;
worker_processes  1;
error_log /var/log/nginx/error.log warn;
pid       /var/run/nginx.pid;
load_module /usr/lib/nginx/modules/ngx_http_brotli_static_module.so;
events {
    worker_connections 1024;
}
http {
    include      mime.types;
    default_type application/octet-stream;
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    access_log /var/log/nginx/access.log main;
    sendfile on;
    keepalive_timeout 65;
    gzip_static   on;
    brotli_static on;
    server {
        listen      80;
        server_name localhost;
        charset utf-8;
        location / {
            root html;
            try_files $uri /index.html;
            etag on;
            expires max;
            add_header Cache-Control public;
            location = /index.html {
                expires 0;
                add_header Cache-Control "no-cache, public, must-revalidate, proxy-revalidate";
            }
        }
    }
}

เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ”เบฒเบงเป‚เบซเบฅเบ”เบฎเบนเบšเบžเบฒเบšเบชเปเบฒเป€เบฅเบฑเบ”เบฎเบนเบšเป„เบ”เป‰เบ—เบตเปˆเบ™เบตเป‰: https://hub.docker.com/r/alexxxnf/nginx-spa. เบกเบฑเบ™เปƒเบŠเป‰เป€เบงเบฅเบฒเป€เบ–เบดเบ‡ 10,5 MB. nginx เบ•เบปเป‰เบ™เบชเบฐเบšเบฑเบšเป„เบ”เป‰เป€เบ–เบดเบ‡ 19,7 MB. เบ„เบงเบฒเบกเบชเบปเบ™เปƒเบˆเบเบดเบฅเบฒเบ‚เบญเบ‡เบ‚เป‰เบญเบเบžเปเปƒเบˆ.

เบเบฒเบ™เบชเบญเบ™เบชเบฐเบ–เบดเบ”เป€เบžเบทเปˆเบญเป€เบ‚เบปเป‰เบฒเปƒเบˆเบ•เบปเบงเปเบ›เบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบก

เป€เบ›เบฑเบ™เบซเบเบฑเบ‡เบ•เป‰เบญเบ‡เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเปƒเบ™ SPA? เบ•เบปเบงเบขเปˆเบฒเบ‡, เป€เบžเบทเปˆเบญเบฅเบฐเบšเบธเบงเปˆเบฒเบˆเบฐเปƒเบŠเป‰ RESTful API เปƒเบ”. เป‚เบ”เบเบ›เบปเบเบเบฐเบ•เบด, เบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบกเบ—เบตเปˆเบ•เป‰เบญเบ‡เบเบฒเบ™เบˆเบฐเบ–เบทเบเป‚เบญเบ™เป„เบ›เบซเบฒ SPA เปƒเบ™เบ‚เบฑเป‰เบ™เบ•เบญเบ™เบเบฒเบ™เบเปเปˆเบชเป‰เบฒเบ‡. เบ–เป‰เบฒเบ—เปˆเบฒเบ™เบ•เป‰เบญเบ‡เบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เบšเบฒเบ‡เบชเบดเปˆเบ‡เบšเบฒเบ‡เบขเปˆเบฒเบ‡, เบ—เปˆเบฒเบ™เบˆเบฐเบ•เป‰เบญเบ‡เบชเป‰เบฒเบ‡เบ„เปเบฒเบฎเป‰เบญเบ‡เบชเบฐเบซเบกเบฑเบเบ„เบทเบ™เปƒเบซเบกเปˆ. เบ‚เป‰เบญเบเบšเปเปˆเบ•เป‰เบญเบ‡เบเบฒเบ™เบกเบฑเบ™. เบ‚เป‰เบญเบเบ•เป‰เบญเบ‡เบเบฒเบ™เปƒเบซเป‰เปเบญเบฑเบšเบžเบฅเบดเป€เบ„เบŠเบฑเบ™เบ–เบทเบเบชเป‰เบฒเบ‡เบ‚เบถเป‰เบ™เบ„เบฑเป‰เบ‡เบ”เบฝเบงเปƒเบ™เบ‚เบฑเป‰เบ™เบ•เบญเบ™ CI, เปเบฅเบฐเบ•เบฑเป‰เบ‡เบ„เปˆเบฒเบซเบผเบฒเบเป€เบ—เบปเปˆเบฒเบ—เบตเปˆเบˆเปเบฒเป€เบ›เบฑเบ™เปƒเบ™เบ‚เบฑเป‰เบ™เบ•เบญเบ™ CD เป‚เบ”เบเปƒเบŠเป‰เบ•เบปเบงเปเบ›เบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบก.

เปเบ™เปˆเบ™เบญเบ™, เป„เบŸเบฅเปŒเบ„เบปเบ‡เบ—เบตเปˆเบ•เบปเบ™เป€เบญเบ‡เบšเปเปˆเป€เบ‚เบปเป‰เบฒเปƒเบˆเบ•เบปเบงเปเบ›เบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบกเปƒเบ”เป†. เป€เบžเบฒเบฐเบชเบฐเบ™เบฑเป‰เบ™, เบ—เปˆเบฒเบ™เบˆเบฐเบ•เป‰เบญเบ‡เปƒเบŠเป‰ trick เป„เบ”เป‰. เปƒเบ™เบฎเบนเบšเบชเบธเบ”เบ—เป‰เบฒเบ, เบ‚เป‰เบญเบเบˆเบฐเบšเปเปˆเป€เบ›เบตเบ”เบ•เบปเบง nginx, เปเบ•เปˆเบกเบตเบชเบฐเบ„เบดเบš shell เบžเบดเป€เบชเบ”เบ—เบตเปˆเบˆเบฐเบญเปˆเบฒเบ™เบ•เบปเบงเปเบ›เบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบก, เบ‚เบฝเบ™เบžเบงเบเบกเบฑเบ™เปƒเบชเปˆเป„เบŸเบฅเปŒเบ„เบปเบ‡เบ—เบตเปˆ, เบšเบตเบšเบญเบฑเบ”เบžเบงเบเบกเบฑเบ™, เปเบฅเบฐเบžเบฝเบ‡เปเบ•เปˆเป‚เบญเบ™เบเบฒเบ™เบ„เบงเบšเบ„เบธเบกเป„เบ›เบซเบฒ nginx.

เบชเปเบฒเบฅเบฑเบšเบˆเบธเบ”เบ›เบฐเบชเบปเบ‡เบ™เบตเป‰, Dockerfile เบชเบฐเบซเบ™เบญเบ‡เบžเบฒเบฅเบฒเบกเบดเป€เบ•เบต ENTRYPOINT. เบ‚เปโ€‹เปƒเบซเป‰โ€‹เบฅเบฒเบงโ€‹เบ‚เบฝเบ™โ€‹เบšเบปเบ”โ€‹เบ•เปเปˆโ€‹เป„เบ›โ€‹เบ™เบตเป‰ (เปƒเบŠเป‰ Angular เป€เบ›เบฑเบ™โ€‹เบ•เบปเบงโ€‹เบขเปˆเบฒเบ‡):

docker-entrypoint.sh

#!/bin/sh
set -e
FLAG_FILE="/configured"
TARGET_DIR="/etc/nginx/html"
replace_vars () {
  ENV_VARS='$(awk 'BEGIN{for(v in ENVIRON) print "

quot;v}')'
# ะ’ Angular ะธั‰ะตะผ ะฟะปะตะนัั…ะพะปะดะตั€ั‹ ะฒ main-ั„ะฐะนะปะฐั…
for f in "$TARGET_DIR"/main*.js; do
# envsubst ะทะฐะผะตะฝัะตั‚ ะฒ ั„ะฐะนะปะฐั… ะฟะปะตะนัั…ะพะปะดะตั€ั‹ ะฝะฐ ะทะฝะฐั‡ะตะฝะธั ะธะท ะฟะตั€ะตะผะตะฝะฝั‹ั… ะพะบั€ัƒะถะตะฝะธั
echo "$(envsubst "$ENV_VARS" < "$f")" > "$f"
done
}
compress () {
for i in $(find "$TARGET_DIR" | grep -E ".css$|.html$|.js$|.svg$|.txt$|.ttf


quot;); do
# ะ˜ัะฟะพะปัŒะทัƒะตะผ ะผะฐะบัะธะผะฐะปัŒะฝัƒัŽ ัั‚ะตะฟะตะฝัŒ ัะถะฐั‚ะธั
gzip -9kf "$i" && brotli -fZ "$i"
done
}
if [ "$1" = 'nginx' ]; then
# ะคะปะฐะณ ะฝัƒะถะตะฝ, ั‡ั‚ะพะฑั‹ ะฒั‹ะฟะพะปะฝะธั‚ัŒ ัะบั€ะธะฟั‚ ั‚ะพะปัŒะบะพ ะฟั€ะธ ัะฐะผะพะผ ะฟะตั€ะฒะพะผ ะทะฐะฟัƒัะบะต
if [ ! -e "$FLAG_FILE" ]; then
echo "Running init script"
echo "Replacing env vars"
replace_vars
echo "Compressing files"
compress
touch $FLAG_FILE
echo "Done"
fi
fi
exec "$@"

เป€เบžเบทเปˆเบญเปƒเบซเป‰เบชเบฐเบ„เบฃเบดเบšเป€เบฎเบฑเบ”เบงเบฝเบเบ‚เบญเบ‡เบกเบฑเบ™, เบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเบ•เป‰เบญเบ‡เบ–เบทเบเบ‚เบฝเบ™เป„เบงเป‰เปƒเบ™เป„เบŸเบฅเปŒ js เปƒเบ™เบฎเบนเบšเปเบšเบšเบ™เบตเป‰: ${API_URL}.

เบกเบฑเบ™เป€เบ›เบฑเบ™เบกเบนเบ™เบ„เปˆเบฒเบ—เบตเปˆเบชเบฑเบ‡เป€เบเบ”เบงเปˆเบฒ SPAs เบ—เบตเปˆเบ—เบฑเบ™เบชเบฐเป„เบซเบกเบชเปˆเบงเบ™เปƒเบซเบเปˆเป€เบžเบตเปˆเบก hashes เบเบฑเบšเป„เบŸเบฅเปŒเบ‚เบญเบ‡เป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒเปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบเบฒเบ™เบเปเปˆเบชเป‰เบฒเบ‡. เบ™เบตเป‰เปเบกเปˆเบ™เบชเบดเปˆเบ‡เบˆเปเบฒเป€เบ›เบฑเบ™เป€เบžเบทเปˆเบญเปƒเบซเป‰เบ•เบปเบงเบ—เปˆเบญเบ‡เป€เบงเบฑเบšเบชเบฒเบกเบฒเบ”เป€เบเบฑเบšเป„เบŸเบฅเปŒเป„เบ”เป‰เบขเปˆเบฒเบ‡เบ›เบญเบ”เป„เบžเปƒเบ™เป€เบงเบฅเบฒเบ”เบปเบ™เบ™เบฒเบ™. เบ–เป‰เบฒเป„เบŸเบฅเปŒเบกเบตเบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™ hash เบ‚เบญเบ‡เบกเบฑเบ™เบˆเบฐเบ›เปˆเบฝเบ™เปเบ›เบ‡, เป€เบŠเบดเปˆเบ‡เบˆเบฐเป€เบฎเบฑเบ”เปƒเบซเป‰เบ•เบปเบงเบ—เปˆเบญเบ‡เป€เบงเบฑเบšเบ”เบฒเบงเป‚เบซเบฅเบ”เป„เบŸเบฅเปŒเบญเบตเบเป€เบ—เบทเปˆเบญเบซเบ™เบถเปˆเบ‡.

เปเบ•เปˆเบซเบ™เป‰เบฒเป€เบชเบเบ”เบฒเบ, เปƒเบ™เบงเบดเบ—เบตเบเบฒเบ™เบ‚เบญเบ‡เบ‚เป‰เบญเบ, เบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเป‚เบ”เบเบœเปˆเบฒเบ™เบ•เบปเบงเปเบ›เบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบกเบšเปเปˆเป„เบ”เป‰เบ™เปเบฒเป„เบ›เบชเบนเปˆเบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เบ‚เบญเบ‡เป„เบŸเบฅเปŒ hash, เบŠเบถเปˆเบ‡เบซเบกเบฒเบเบ„เบงเบฒเบกเบงเปˆเบฒ cache เบ‚เบญเบ‡เบ•เบปเบงเบ—เปˆเบญเบ‡เป€เบงเบฑเบšเบ•เป‰เบญเบ‡เบšเปเปˆเบ–เบทเบเบ•เป‰เบญเบ‡เปƒเบ™เบ—เบฒเบ‡เบญเบทเปˆเบ™. เบ‚เป‰เบญเบเบšเปเปˆเบกเบตเบšเบฑเบ™เบซเบฒเบ™เบตเป‰เป€เบžเบฒเบฐเบงเปˆเบฒเบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเบ—เบตเปˆเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™เบ–เบทเบเบ™เปเบฒเป„เบ›เปƒเบŠเป‰เปƒเบ™เบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบกเบ—เบตเปˆเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™.

เป€เบญเบปเบฒเบฎเบนเบšเบชเบธเบ”เบ—เป‰เบฒเบเบฎเปˆเบงเบกเบเบฑเบ™

เบชเบธเบ”เบ—เป‰เบฒเบ.

dockerfile

# ะŸะตั€ะฒั‹ะน ะฑะฐะทะพะฒั‹ะน ะพะฑั€ะฐะท ะดะปั ัะฑะพั€ะบะธ
FROM alexxxnf/spa-builder as builder
# ะงั‚ะพะฑั‹ ัั„ั„ะบั‚ะธะฒะฝะตะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะบััˆ Docker-ะฐ, ัะฝะฐั‡ะฐะปะฐ ัƒัั‚ะฐะฝะฐะฒะปะธะฒะฐะตะผ ั‚ะพะปัŒะบะพ ะทะฐะฒะธัะธะผะพัั‚ะธ
COPY ./package.json ./package-lock.json /app/
RUN cd /app && npm ci --no-audit
# ะŸะพั‚ะพะผ ัะพะฑะธั€ะฐะตะผ ัะฐะผะพ ะฟั€ะธะปะพะถะตะฝะธะต
COPY . /app
RUN cd /app && npm run build -- --prod --configuration=docker

# ะ’ั‚ะพั€ะพะน ะฑะฐะทะพะฒั‹ะน ะพะฑั€ะฐะท ะดะปั ั€ะฐะทะดะฐั‡ะธ
FROM alexxxnf/nginx-spa
# ะ—ะฐะฑะธั€ะฐะตะผ ะธะท ะฟะตั€ะฒะพะณะพ ะพะฑั€ะฐะทะฐ ัะฝะฐั‡ะฐะปะฐ ะบะพะผะฟั€ะตััะพั€
COPY --from=builder /usr/local/bin/brotli /usr/local/bin
# ะŸะพั‚ะพะผ ะดะพะฑะฐะฒะปัะตะผ ั‡ัƒะดะพ-ัะบั€ะธะฟั‚
COPY ./docker/docker-entrypoint.sh /docker-entrypoint.sh
# ะ˜ ะฒ ะบะพะฝั†ะต ะทะฐะฑะธั€ะฐะตะผ ัะฐะผะพ ะฟั€ะธะปะพะถะตะฝะธะต
COPY --from=builder /app/dist/app /etc/nginx/html/
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]

เปƒเบ™เบ›เบฑเบ”เบˆเบธเบšเบฑเบ™เบฎเบนเบšเบžเบฒเบšเบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบšเบชเบฒเบกเบฒเบ”เป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™เบ›เบฐเบเบญเบšเปเบฅเบฐเบ™เปเบฒเปƒเบŠเป‰เบ—เบธเบเบšเปˆเบญเบ™.

เปเบซเบผเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™: www.habr.com