เชธเชฟเช‚เช—เชฒ เชชเซ‡เชœ เชเชชเซเชฒเชฟเช•เซ‡เชถเชจเชจเชพ เชตเชฟเชคเชฐเชฃ เชฎเชพเชŸเซ‡ เชกเซ‹เช•เชฐ เช›เชฌเซ€

เชธเชฟเช‚เช—เชฒ-เชชเซ‡เชœ เชเชชเซเชฒเชฟเช•เซ‡เชถเชจ (SPA) เช เชธเซเชŸเซ‡เชŸเชฟเช• JavaScript เช…เชจเซ‡ HTML เชซเชพเชˆเชฒเซ‹ เชคเซ‡เชฎเชœ เชˆเชฎเซ‡เชœเซ€เชธ เช…เชจเซ‡ เช…เชจเซเชฏ เชธเช‚เชธเชพเชงเชจเซ‹เชจเซ‹ เชธเชฎเซ‚เชน เช›เซ‡. เช•เชพเชฐเชฃ เช•เซ‡ เชคเซ‡เช“ เช—เชคเชฟเชถเซ€เชฒ เชฐเซ€เชคเซ‡ เชฌเชฆเชฒเชพเชคเชพ เชจเชฅเซ€, เชคเซ‡เชฎเชจเซ‡ เช‘เชจเชฒเชพเช‡เชจ เชชเซเชฐเช•เชพเชถเชฟเชค เช•เชฐเชตเซเช‚ เช–เซ‚เชฌ เชœ เชธเชฐเชณ เช›เซ‡. เช†เชจเชพ เชฎเชพเชŸเซ‡ เชฎเซ‹เชŸเซ€ เชธเช‚เช–เซเชฏเชพเชฎเชพเช‚ เชธเชธเซเชคเซ€ เช…เชจเซ‡ เชฎเชซเชค เชธเซ‡เชตเชพเช“ เชชเชฃ เช›เซ‡, เชœเซ‡ เชธเชพเชฆเชพ GitHub เชชเซƒเชทเซเช เซ‹เชฅเซ€ เชถเชฐเซ‚ เชฅเชพเชฏ เช›เซ‡ (เช…เชจเซ‡ เช•เซ‡เชŸเชฒเชพเช• เชฎเชพเชŸเซ‡ narod.ru เชธเชพเชฅเซ‡ เชชเชฃ) เช…เชจเซ‡ เชเชฎเซ‡เชเซ‹เชจ S3 เชœเซ‡เชตเชพ CDN เชธเชพเชฅเซ‡ เชธเชฎเชพเชชเซเชค เชฅเชพเชฏ เช›เซ‡. เชœเซ‹ เช•เซ‡, เชฎเชพเชฐเซ‡ เช•เช‚เชˆเช• เชฌเซ€เชœเซเช‚ เชœเซ‹เชˆเช เช›เซ‡.

เชฎเชจเซ‡ SPA เชธเชพเชฅเซ‡ เชกเซ‹เช•เชฐ เช‡เชฎเซ‡เชœเชจเซ€ เชœเชฐเซ‚เชฐ เชนเชคเซ€ เชœเซ‡เชฅเซ€ เช•เชฐเซ€เชจเซ‡ เชคเซ‡เชจเซ‡ เช•เซเชฌเชฐเชจเซ‡เชŸเซเชธ เช•เซเชฒเชธเซเชŸเชฐเชจเชพ เชญเชพเช— เชฐเซ‚เชชเซ‡ เช‰เชคเซเชชเชพเชฆเชจเชฎเชพเช‚ เช…เชจเซ‡ เชฌเซ‡เช•-เชเชจเซเชก เชกเซ‡เชตเชฒเชชเชฐเชจเชพ เชฎเชถเซ€เชจ เชชเชฐ เชธเชฐเชณเชคเชพเชฅเซ€ เชฒเซ‹เชจเซเชš เช•เชฐเซ€ เชถเช•เชพเชฏ เช•เซ‡ เชœเซ‡เชจเซ‡ SPA เชถเซเช‚ เช›เซ‡ เชคเซ‡เชจเซ€ เช•เซ‹เชˆ เชœเชพเชฃ เชจเชฅเซ€.

เชฎเซ‡เช‚ เชฎเชพเชฐเชพ เชฎเชพเชŸเซ‡ เชจเซ€เชšเซ‡เชจเซ€ เช›เชฌเซ€ เช†เชตเชถเซเชฏเช•เชคเชพเช“ เชจเช•เซเช•เซ€ เช•เชฐเซ€ เช›เซ‡:

  • เช‰เชชเชฏเซ‹เช—เชฎเชพเช‚ เชธเชฐเชณเชคเชพ (เชชเชฐเช‚เชคเซ เชเชธเซ‡เชฎเซเชฌเชฒเซ€ เชจเชนเซ€เช‚);
  • เชกเชฟเชธเซเช• เช…เชจเซ‡ เชฐเซ‡เชฎ เชฌเช‚เชจเซ‡เชจเซ€ เชฆเซเชฐเชทเซเชŸเชฟเช เชจเซเชฏเซ‚เชจเชคเชฎ เช•เชฆ;
  • เชชเชฐเซเชฏเชพเชตเชฐเชฃ เชšเชฒเซ‹ เชฆเซเชตเชพเชฐเชพ เชฐเซ‚เชชเชฐเซ‡เช–เชพเช‚เช•เชจ เชœเซ‡เชฅเซ€ เช›เชฌเซ€เชจเซ‹ เช‰เชชเชฏเซ‹เช— เชตเชฟเชตเชฟเชง เชตเชพเชคเชพเชตเชฐเชฃเชฎเชพเช‚ เชฅเชˆ เชถเช•เซ‡;
  • เชซเชพเช‡เชฒเซ‹เชจเซเช‚ เชธเซŒเชฅเซ€ เช•เชพเชฐเซเชฏเช•เซเชทเชฎ เชตเชฟเชคเชฐเชฃ.

เช†เชœเซ‡ เชนเซเช‚ เชคเชฎเชจเซ‡ เช•เชนเซ€เชถ เช•เซ‡ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡:

  • เช†เช‚เชคเชฐเชกเชพ nginx;
  • เชธเซเชคเซเชฐเซ‹เชคเซ‹เชฎเชพเช‚เชฅเซ€ เชฌเซเชฐเซ‹เชŸเชฒเซ€ เชฌเชจเชพเชตเซ‹;
  • เชชเชฐเซเชฏเชพเชตเชฐเชฃ เชšเชฒเซ‹เชจเซ‡ เชธเชฎเชœเชตเชพ เชฎเชพเชŸเซ‡ เชธเซเชฅเชฟเชฐ เชซเชพเช‡เชฒเซ‹เชจเซ‡ เชถเซ€เช–เชตเซ‹;
  • เช…เชจเซ‡ เช…เชฒเชฌเชคเซเชค เช† เชฌเชงเชพเชฎเชพเช‚เชฅเซ€ เชกเซ‹เช•เชฐ เช‡เชฎเซ‡เชœ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชเชธเซ‡เชฎเซเชฌเชฒ เช•เชฐเชตเซ€.

เช† เชฒเซ‡เช–เชจเซ‹ เชนเซ‡เชคเซ เชฎเชพเชฐเชพ เช…เชจเซเชญเชตเชจเซ‡ เชถเซ‡เชฐ เช•เชฐเชตเชพเชจเซ‹ เช…เชจเซ‡ เช…เชจเซเชญเชตเซ€ เชธเชฎเซเชฆเชพเชฏเชจเชพ เชธเชญเซเชฏเซ‹เชจเซ‡ เชฐเชšเชจเชพเชคเซเชฎเช• เชŸเซ€เช•เชพ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เช‰เชถเซเช•เซ‡เชฐเชตเชพเชจเซ‹ เช›เซ‡.

เชเชธเซ‡เชฎเซเชฌเชฒเซ€ เชฎเชพเชŸเซ‡ เชเช• เช›เชฌเซ€ เชฌเชจเชพเชตเชตเซ€

เช…เช‚เชคเชฟเชฎ เชกเซ‹เช•เชฐ เช‡เชฎเซ‡เชœเชจเซ‡ เช•เชฆเชฎเชพเช‚ เชจเชพเชจเซ€ เชฌเชจเชพเชตเชตเชพ เชฎเชพเชŸเซ‡, เชคเชฎเชพเชฐเซ‡ เชฌเซ‡ เชจเชฟเชฏเชฎเซ‹เชจเซเช‚ เชชเชพเชฒเชจ เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡: เชจเซเชฏเซ‚เชจเชคเชฎ เชธเซเชคเชฐเซ‹ เช…เชจเซ‡ เชจเซเชฏเซ‚เชจเชคเชฎ เชฌเซ‡เช เช‡เชฎเซ‡เชœ. เชธเซŒเชฅเซ€ เชจเชพเชจเซ€ เชฌเซ‡เช เช‡เชฎเซ‡เชœเชฎเชพเช‚เชจเซ€ เชเช• เช†เชฒเซเชชเชพเช‡เชจ เชฒเชฟเชจเช•เซเชธ เช‡เชฎเซ‡เชœ เช›เซ‡, เชคเซ‡เชฅเซ€ เชนเซเช‚ เชคเซ‡ เชœ เชชเชธเช‚เชฆ เช•เชฐเซ€เชถ. เช•เซ‡เชŸเชฒเชพเช• เชเชตเซ€ เชฆเชฒเซ€เชฒ เช•เชฐเซ€ เชถเช•เซ‡ เช›เซ‡ เช•เซ‡ เช†เชฒเซเชชเชพเช‡เชจ เช‰เชคเซเชชเชพเชฆเชจ เชฎเชพเชŸเซ‡ เชฏเซ‹เช—เซเชฏ เชจเชฅเซ€, เช…เชจเซ‡ เชคเซ‡ เชฏเซ‹เช—เซเชฏ เชนเซ‹เชˆ เชถเช•เซ‡ เช›เซ‡. เชชเชฐเช‚เชคเซ เชตเซเชฏเช•เซเชคเชฟเช—เชค เชฐเซ€เชคเซ‡, เชฎเชจเซ‡ เชคเซ‡เชจเซ€ เชธเชพเชฅเซ‡ เช•เซเชฏเชพเชฐเซ‡เชฏ เช•เซ‹เชˆ เชธเชฎเชธเซเชฏเชพ เชจเชฅเซ€ เช…เชจเซ‡ เชคเซ‡เชจเซ€ เชธเชพเชฎเซ‡ เช•เซ‹เชˆ เชฆเชฒเซ€เชฒเซ‹ เชจเชฅเซ€.

เช“เช›เชพ เชธเซเชคเชฐเซ‹ เชฐเชพเช–เชตเชพ เชฎเชพเชŸเซ‡, เชนเซเช‚ เชˆเชฎเซ‡เชœเชจเซ‡ 2 เชคเชฌเช•เซเช•เชพเชฎเชพเช‚ เชเชธเซ‡เชฎเซเชฌเชฒ เช•เชฐเซ€เชถ. เชชเซเชฐเชฅเชฎ เชกเซเชฐเชพเชซเซเชŸ เช›เซ‡; เชฌเชงเซ€ เชธเชนเชพเชฏเช• เช‰เชชเชฏเซ‹เช—เชฟเชคเชพเช“ เช…เชจเซ‡ เช…เชธเซเชฅเชพเชฏเซ€ เชซเชพเช‡เชฒเซ‹ เชคเซ‡เชฎเชพเช‚ เชฐเชนเซ‡เชถเซ‡. เช…เชจเซ‡ เช…เช‚เชคเชฟเชฎ เชคเชฌเช•เซเช•เชพเชฎเชพเช‚ เชนเซเช‚ เชซเช•เซเชค เชเชชเซเชฒเชฟเช•เซ‡เชถเชจเชจเซเช‚ เช…เช‚เชคเชฟเชฎ เชธเช‚เชธเซเช•เชฐเชฃ เชฒเช–เซ€เชถ.

เชšเชพเชฒเซ‹ เชธเชนเชพเชฏเช• เช›เชฌเซ€ เชธเชพเชฅเซ‡ เชชเซเชฐเชพเชฐเช‚เชญ เช•เชฐเซ€เช.

SPA เชเชชเซเชฒเชฟเช•เซ‡เชถเชจ เช•เชฎเซเชชเชพเช‡เชฒ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡, เชคเชฎเชพเชฐเซ‡ เชธเชพเชฎเชพเชจเซเชฏ เชฐเซ€เชคเซ‡ node.js เชจเซ€ เชœเชฐเซ‚เชฐ เชชเชกเซ‡ เช›เซ‡. เชนเซเช‚ เชธเชคเซเชคเชพเชตเชพเชฐ เช›เชฌเซ€ เชฒเชˆเชถ, เชœเซ‡ npm เช…เชจเซ‡ เชฏเชพเชฐเซเชจ เชชเซ‡เช•เซ‡เชœ เชฎเซ‡เชจเซ‡เชœเชฐเซ‹ เชธเชพเชฅเซ‡ เชชเชฃ เช†เชตเซ‡ เช›เซ‡. เชฎเชพเชฐเชพ เชชเซ‹เชคเชพเชจเชพ เชตเชคเซ€, เชนเซเช‚ เชจเซ‹เชก-เชœเซ€เชช เช‰เชฎเซ‡เชฐเซ€เชถ, เชœเซ‡ เช•เซ‡เชŸเชฒเชพเช• npm เชชเซ‡เช•เซ‡เชœเซ‹ เชฌเชจเชพเชตเชตเชพ เชฎเชพเชŸเซ‡ เชœเชฐเซ‚เชฐเซ€ เช›เซ‡, เช…เชจเซ‡ Google เชคเชฐเชซเชฅเซ€ Brotli เช•เซ‹เชฎเซเชชเซเชฐเซ‡เชธเชฐ, เชœเซ‡ เช…เชฎเชจเซ‡ เชชเช›เซ€เชฅเซ€ เช‰เชชเชฏเซ‹เช—เซ€ เชฅเชถเซ‡.

เชŸเชฟเชชเซเชชเชฃเซ€เช“ เชธเชพเชฅเซ‡ เชกเซ‹เช•เชฐเชซเชพเช‡เชฒ.

# ะ‘ะฐะทะพะฒั‹ะน ะพะฑั€ะฐะท
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

เชชเชนเซ‡เชฒเซ‡เชฅเซ€ เชœ เช…เชนเซ€เช‚ เชนเซเช‚ เชฎเชฟเชจเชฟเชฎเชฒเชฟเชเชฎ เชฎเชพเชŸเซ‡ เชฒเชกเซ€ เชฐเชนเซเชฏเซ‹ เช›เซเช‚, เชคเซ‡เชฅเซ€ เช›เชฌเซ€ เชเช• เชฎเซ‹เชŸเซ€ เชŸเซ€เชฎ เชฆเซเชตเชพเชฐเชพ เชเช•เชธเชพเชฅเซ‡ เชฎเซ‚เช•เชตเชพเชฎเชพเช‚ เช†เชตเซ€ เช›เซ‡.

เชธเชฎเชพเชชเซเชค เชฅเชฏเซ‡เชฒ เช›เชฌเซ€ เช…เชนเซ€เช‚ เชฎเชณเซ€ เชถเช•เซ‡ เช›เซ‡: https://hub.docker.com/r/alexxxnf/spa-builder. เชคเซ‡เชฎ เช›เชคเชพเช‚ เชนเซเช‚ เชญเชฒเชพเชฎเชฃ เช•เชฐเซเช‚ เช›เซเช‚ เช•เซ‡ เช…เชจเซเชฏ เชฒเซ‹เช•เซ‹เชจเซ€ เช›เชฌเซ€เช“ เชชเชฐ เช†เชงเชพเชฐ เชจ เชฐเชพเช–เซ‹ เช…เชจเซ‡ เชคเชฎเชพเชฐเซ€ เชชเซ‹เชคเชพเชจเซ€ เช›เชฌเซ€เช“ เชเช•เชคเซเชฐเชฟเชค เช•เชฐเซ‹.

nginx

เชคเชฎเซ‡ เชธเซเชฅเชฟเชฐ เชธเชพเชฎเช—เซเชฐเซ€ เชตเชฟเชคเชฐเชฟเชค เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เช•เซ‹เชˆเชชเชฃ เชตเซ‡เชฌ เชธเชฐเซเชตเชฐเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹. เชนเซเช‚ nginx เชธเชพเชฅเซ‡ เช•เชพเชฎ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชŸเซ‡เชตเชพเชฏเซ‡เชฒเซ‹ เช›เซเช‚, เชคเซ‡เชฅเซ€ เชนเชตเซ‡ เชนเซเช‚ เชคเซ‡เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชถ.

Nginx เชชเชพเชธเซ‡ เชธเชคเซเชคเชพเชตเชพเชฐ เชกเซ‹เช•เชฐ เช‡เชฎเซ‡เชœ เช›เซ‡, เชชเชฐเช‚เชคเซ เชคเซ‡เชฎเชพเช‚ เชธเชฐเชณ เชธเซเชฅเชฟเชฐ เชตเชฟเชคเชฐเชฃ เชฎเชพเชŸเซ‡ เช˜เชฃเชพ เชฌเชงเชพ เชฎเซ‹เชกเซเชฏเซเชฒเซ‹ เช›เซ‡. เชกเชฟเชฒเชฟเชตเชฐเซ€เชฎเชพเช‚ เช•เซเชฏเชพเชจเซ‹ เชธเชฎเชพเชตเซ‡เชถ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซ‹ เช›เซ‡ เชคเซ‡ เชตเชฟเชถเซ‡เชท เชŸเซ€เชฎ เชฆเซเชตเชพเชฐเชพ เช…เชฅเชตเชพ เชธเชคเซเชคเชพเชตเชพเชฐ เชกเซ‹เช•เชฐเชซเชพเช‡เชฒเชฎเชพเช‚ เชœเซ‹เชˆ เชถเช•เชพเชฏ เช›เซ‡.

$ docker เชฐเชจ --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

เชนเซเช‚ เชกเซ‹เช•เชฐเชซเชพเช‡เชฒเชจเซ‹ เช†เชงเชพเชฐ เชคเชฐเซ€เช•เซ‡ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชถ, เชชเชฐเช‚เชคเซ เชนเซเช‚ เชคเซ‡เชฎเชพเช‚ เชซเช•เซเชค เชคเซ‡ เชœ เช›เซ‹เชกเซ€เชถ เชœเซ‡ เชธเซเชฅเชฟเชฐ เชธเชพเชฎเช—เซเชฐเซ€เชจเชพ เชตเชฟเชคเชฐเชฃ เชฎเชพเชŸเซ‡ เชœเชฐเซ‚เชฐเซ€ เช›เซ‡. เชฎเชพเชฐเซเช‚ เชธเช‚เชธเซเช•เชฐเชฃ HTTPS เชชเชฐ เช•เชพเชฎ เช•เชฐเซ€ เชถเช•เชถเซ‡ เชจเชนเซ€เช‚, เช…เชงเชฟเช•เซƒเชคเชคเชพเชจเซ‡ เชธเชฎเชฐเซเชฅเชจ เช†เชชเชถเซ‡ เชจเชนเซ€เช‚ เช…เชจเซ‡ เช˜เชฃเซเช‚ เชฌเชงเซเช‚. เชชเชฐเช‚เชคเซ เชฎเชพเชฐเซเช‚ เชธเช‚เชธเซเช•เชฐเชฃ เชฌเซเชฐเซ‹เชŸเชฒเซ€ เช…เชฒเซเช—เซ‹เชฐเชฟเชงเชฎ เชธเชพเชฅเซ‡ เชธเช‚เช•เซเชšเชฟเชค เชซเชพเช‡เชฒเซ‹เชจเซ‡ เชตเชฟเชคเชฐเชฟเชค เช•เชฐเชตเชพเชฎเชพเช‚ เชธเช•เซเชทเชฎ เชนเชถเซ‡, เชœเซ‡ gzip เช•เชฐเชคเชพเช‚ เชธเชนเซ‡เชœ เชตเชงเซ เช•เชพเชฐเซเชฏเช•เซเชทเชฎ เช›เซ‡. เช…เชฎเซ‡ เชซเชพเช‡เชฒเซ‹เชจเซ‡ เชเช•เชตเชพเชฐ เชธเช‚เช•เซเชšเชฟเชค เช•เชฐเซ€เชถเซเช‚; เชซเซเชฒเชพเชฏ เชชเชฐ เช† เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เชจเชฅเซ€.

เช† เชคเซ‡ เชกเซ‹เช•เชฐเชซเชพเช‡เชฒ เช›เซ‡ เชœเซ‡เชจเซ‹ เชฎเซ‡เช‚ เช…เช‚เชค เช•เชฐเซเชฏเซ‹ เช›เซ‡. เชฐเชถเชฟเชฏเชจเชฎเชพเช‚ เชŸเชฟเชชเซเชชเชฃเซ€เช“ เชฎเชพเชฐเซ€ เช›เซ‡, เช…เช‚เช—เซเชฐเซ‡เชœเซ€เชฎเชพเช‚ - เชฎเซ‚เชณเชฎเชพเช‚เชฅเซ€.

เชกเซ‹เช•เชฐเชซเชพเช‡เชฒ

# ะ‘ะฐะทะพะฒั‹ะน ะพะฑั€ะฐะท ัะฝะพะฒะฐ 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 เชฎเชพเช‚ เชธเซเชฅเชพเชจเชพเช‚เชคเชฐเชฟเชค เชฅเชพเชฏ เช›เซ‡. เชœเซ‹ เชคเชฎเชพเชฐเซ‡ เช•เช‚เชˆเช• เชฌเชฆเชฒเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เชนเซ‹เชฏ, เชคเซ‹ เชคเชฎเชพเชฐเซ‡ เชเชชเซเชฒเชฟเช•เซ‡เชถเชจ เชซเชฐเซ€เชฅเซ€ เชฌเชจเชพเชตเชตเซ€ เชชเชกเชถเซ‡. เชฎเชพเชฐเซ‡ เชคเซ‡ เชจเชฅเซ€ เชœเซ‹เชˆเชคเซเช‚. เชนเซเช‚ เชˆเชšเซเช›เซเช‚ เช›เซเช‚ เช•เซ‡ เชเชชเซเชฒเซ€เช•เซ‡เชถเชจ เชธเซ€เช†เชˆ เชธเซเชŸเซ‡เชœ เชชเชฐ เชเช•เชตเชพเชฐ เชฌเชจเซ‡ เช…เชจเซ‡ เชธเซ€เชกเซ€ เชธเซเชŸเซ‡เชœ เชชเชฐ เชเชจเซเชตเชพเชฏเชฐเซเชจเชฎเซ‡เชจเซเชŸ เชตเซ‡เชฐเซ€เชเชฌเชฒเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เชœเชฐเซ‚เชฐเซ€ เชนเซ‹เชฏ เชคเซ‡เชŸเชฒเซเช‚ เชฐเซ‚เชชเชฐเซ‡เช–เชพเช‚เช•เชฟเชค เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡.

เช…เชฒเชฌเชคเซเชค, เชธเซเชŸเซ‡เชŸเชฟเช• เชซเชพเช‡เชฒเซ‹ เชชเซ‹เชคเซ‡ เช•เซ‹เชˆเชชเชฃ เชชเชฐเซเชฏเชพเชตเชฐเชฃ เชšเชฒเซ‹เชจเซ‡ เชธเชฎเชœเซ€ เชถเช•เชคเซ€ เชจเชฅเซ€. เชคเซ‡เชฅเซ€, เชคเชฎเชพเชฐเซ‡ เชฏเซเช•เซเชคเชฟเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเซ‹ เชชเชกเชถเซ‡. เช…เช‚เชคเชฟเชฎ เชˆเชฎเซ‡เชœเชฎเชพเช‚, เชนเซเช‚ nginx เชฒเซ‹เชจเซเชš เช•เชฐเซ€เชถ เชจเชนเซ€เช‚, เชชเชฐเช‚เชคเซ เชเช• เช–เชพเชธ เชถเซ‡เชฒ เชธเซเช•เซเชฐเชฟเชชเซเชŸ เช•เซ‡ เชœเซ‡ เชชเชฐเซเชฏเชพเชตเชฐเชฃ เชšเชฒเซ‹เชจเซ‡ เชตเชพเช‚เชšเชถเซ‡, เชคเซ‡เชฎเชจเซ‡ เชธเซเชฅเชฟเชฐ เชซเชพเชˆเชฒเซ‹ เชชเชฐ เชฒเช–เชถเซ‡, เชคเซ‡เชฎเชจเซ‡ เชธเช‚เช•เซเชšเชฟเชค เช•เชฐเชถเซ‡ เช…เชจเซ‡ เชชเช›เซ€ เชœ เชจเชฟเชฏเช‚เชคเซเชฐเชฃเชจเซ‡ nginx เชชเชฐ เชธเซเชฅเชพเชจเชพเช‚เชคเชฐเชฟเชค เช•เชฐเชถเซ‡.

เช† เชนเซ‡เชคเซ เชฎเชพเชŸเซ‡, เชกเซ‹เช•เชฐเชซเชพเช‡เชฒ ENTRYPOINT เชชเชฐเชฟเชฎเชพเชฃ เชชเซเชฐเชฆเชพเชจ เช•เชฐเซ‡ เช›เซ‡. เชšเชพเชฒเซ‹ เชคเซ‡เชจเซ‡ เชจเซ€เชšเซ‡เชจเซ€ เชธเซเช•เซเชฐเชฟเชชเซเชŸ เช†เชชเซ€เช (เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡ เช•เซ‹เชฃเซ€เชฏเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡):

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}.

เชคเซ‡ เชจเซ‹เช‚เชงเชตเซเช‚ เชฏเซ‹เช—เซเชฏ เช›เซ‡ เช•เซ‡ เชฎเซ‹เชŸเชพ เชญเชพเช—เชจเชพ เช†เชงเซเชจเชฟเช• SPA เชคเซ‡เชฎเชจเซ€ เชซเชพเช‡เชฒเซ‹เชฎเชพเช‚ เชนเซ‡เชถ เช‰เชฎเซ‡เชฐเซ‡ เช›เซ‡ เชœเซเชฏเชพเชฐเซ‡ เชฌเชฟเชฒเซเชกเชฟเช‚เช— เชฌเชจเชพเชตเซ‡ เช›เซ‡. เช† เชœเชฐเซ‚เชฐเซ€ เช›เซ‡ เชœเซ‡เชฅเซ€ เชฌเซเชฐเชพเช‰เชเชฐ เชฒเชพเช‚เชฌเชพ เชธเชฎเชฏ เชธเซเชงเซ€ เชซเชพเช‡เชฒเชจเซ‡ เชธเซเชฐเช•เซเชทเชฟเชค เชฐเซ€เชคเซ‡ เช•เซ‡เชถ เช•เชฐเซ€ เชถเช•เซ‡. เชœเซ‹ เชซเชพเช‡เชฒ เชฌเชฆเชฒเชพเชฏ เช›เซ‡, เชคเซ‹ เชคเซ‡เชจเซ€ เชนเซ‡เชถ เชฌเชฆเชฒเชพเชถเซ‡, เชœเซ‡ เชฌเชฆเชฒเชพเชฎเชพเช‚ เชฌเซเชฐเชพเช‰เชเชฐเชจเซ‡ เชซเชฐเซ€เชฅเซ€ เชซเชพเช‡เชฒ เชกเชพเช‰เชจเชฒเซ‹เชก เช•เชฐเชตเชพ เชฆเชฌเชพเชฃ เช•เชฐเชถเซ‡.

เช•เชฎเชจเชธเซ€เชฌเซ‡, เชฎเชพเชฐเซ€ เชชเชฆเซเชงเชคเชฟเชฎเชพเช‚, เชชเชฐเซเชฏเชพเชตเชฐเชฃ เชšเชฒเซ‹ เชฆเซเชตเชพเชฐเชพ เชฐเซ‚เชชเชฐเซ‡เช–เชพเช‚เช•เชจ เชฌเชฆเชฒเชตเชพเชฅเซ€ เชซเชพเช‡เชฒ เชนเซ‡เชถเชฎเชพเช‚ เชซเซ‡เชฐเชซเชพเชฐ เชฅเชคเซ‹ เชจเชฅเซ€, เชœเซ‡เชจเซ‹ เช…เชฐเซเชฅ เช›เซ‡ เช•เซ‡ เชฌเซเชฐเชพเช‰เชเชฐ เช•เซ‡เชถ เช…เชจเซเชฏ เชฐเซ€เชคเซ‡ เช…เชฎเชพเชจเซเชฏ เชนเซ‹เชตเซเช‚ เช†เชตเชถเซเชฏเช• เช›เซ‡. เชฎเชจเซ‡ เช† เชธเชฎเชธเซเชฏเชพ เชจเชฅเซ€ เช•เชพเชฐเชฃ เช•เซ‡ เชตเชฟเชตเชฟเชง เชฐเซ‚เชชเชฐเซ‡เช–เชพเช‚เช•เชจเซ‹ เชตเชฟเชตเชฟเชง เชตเชพเชคเชพเชตเชฐเชฃเชฎเชพเช‚ เชœเชฎเชพเชตเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡.

เช…เช‚เชคเชฟเชฎ เช›เชฌเซ€ เชเช•เชธเชพเชฅเซ‡ เชฎเซ‚เช•เชตเซ€

เช›เซ‡เชฒเซเชฒเซ‡.

เชกเซ‹เช•เชฐเชซเชพเช‡เชฒ

# ะŸะตั€ะฒั‹ะน ะฑะฐะทะพะฒั‹ะน ะพะฑั€ะฐะท ะดะปั ัะฑะพั€ะบะธ
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