ื“ืึธืงืขืจ ื‘ื™ืœื“ ืคึฟืึทืจ ืคืึทืจืฉืคึผืจื™ื™ื˜ื•ื ื’ ืคื•ืŸ ืื™ื™ืŸ ื‘ืœืึทื˜ ืึทืคึผืคึผืœื™ืงืึทื˜ื™ืึธืŸ

ืื™ื™ืŸ-ื‘ืœืึทื˜ ืึทืคึผืคึผืœื™ืงืึทื˜ื™ืึธืŸ (SPA) ืื™ื– ืึท ืกื›ื•ื ืคื•ืŸ ืกื˜ืึทื˜ื™ืง ื“ื–ืฉืึทื•ื•ืึทืกืงืจื™ืคึผื˜ ืื•ืŸ HTML ื˜ืขืงืขืก, ื•ื•ื™ ื’ืขื–ื•ื ื˜ ื•ื•ื™ ื‘ื™ืœื“ืขืจ ืื•ืŸ ืื ื“ืขืจืข ืจืขืกื•ืจืกืŸ. ื•ื•ื™ื™ึทืœ ื–ื™ื™ ื˜ืึธืŸ ื ื™ื˜ ื˜ื•ื™ืฉืŸ ื“ื™ื ืึทืžื™ืงืึทืœืœื™, ืืจื•ื™ืกื’ืขื‘ืŸ ื–ื™ื™ ืึธื ืœื™ื™ืŸ ืื™ื– ื–ื™ื™ืขืจ ื’ืจื™ื ื’. ืขืก ื–ืขื ืขืŸ ืึท ื’ืจื•ื™ืก ื ื•ืžืขืจ ืคื•ืŸ ื‘ื™ืœื™ืง ืื•ืŸ ืืคื™ืœื• ืคืจื™ื™ ื‘ืึทื“ื™ื ื•ื ื’ืก ืคึฟืึทืจ ื“ืขื, ืกื˜ืึทืจื˜ื™ื ื’ ืžื™ื˜ ืึท ืคึผืฉื•ื˜ GitHub ื‘ืœืขื˜ืขืจ (ืื•ืŸ ืคึฟืึทืจ ืขื˜ืœืขื›ืข ืืคื™ืœื• ืžื™ื˜ narod.ru) ืื•ืŸ ืขื ื“ื™ืงืŸ ืžื™ื˜ ืึท CDN ื•ื•ื™ Amazon S3. ืึธื‘ืขืจ, ืื™ืš ื“ืืจืฃ ืขืคึผืขืก ืึทื ื“ืขืจืฉ.

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

ืื™ืš ื”ืื‘ ื‘ืืฉืœืืกืŸ ื“ื™ ืคืืœื’ืขื ื“ืข ื‘ื™ืœื“ ืจืขืงื•ื•ื™ืจืขืžืขื ืฅ ืคึฟืึทืจ ื–ื™ืš:

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

ื”ื™ื™ึทื ื˜ ืื™ืš ื•ื•ืขืœ ื–ืึธื’ืŸ ืื™ืจ ื•ื•ื™:

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

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

ื‘ื•ื™ืขืŸ ืึท ื‘ื™ืœื“ ืคึฟืึทืจ ืคึฟืึทืจื–ืึทืžืœื•ื ื’

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

ืฆื• ื”ืึธื‘ืŸ ื•ื•ื™ื™ื ื™ืงืขืจืข ืœื™ื™ึทืขืจืก, ืื™ืš ื•ื•ืขืœ ืึทืกืขืžื‘ืึทืœ ื“ื™ ื‘ื™ืœื“ ืื™ืŸ 2 ืกื˜ืึทื’ืขืก. ื“ืขืจ ืขืจืฉื˜ืขืจ ืื™ื– ืึท ืคึผืœืึทืŸ; ืึทืœืข ืึทื’ื–ื™ืœื™ืขืจื™ ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืื•ืŸ ืฆื™ื™ึทื˜ื•ื•ื™ื™ึทืœื™ืง ื˜ืขืงืขืก ื•ื•ืขื˜ ื‘ืœื™ื™ึทื‘ืŸ ืื™ืŸ ืขืก. ืื•ืŸ ืื™ืŸ ื“ื™ ืœืขืฆื˜ ื‘ื™ื ืข ืื™ืš ื•ื•ืขืœ ื ืึธืจ ืฉืจื™ื™ึทื‘ืŸ ื“ื™ ืœืขืฆื˜ ื•ื•ืขืจืกื™ืข ืคื•ืŸ โ€‹โ€‹ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ.

ื–ืืœ ืก ืึธื ื”ื™ื™ื‘ืŸ ืžื™ื˜ ื“ื™ ืึทื’ื–ื™ืœื™ืขืจื™ ื‘ื™ืœื“.

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

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

ื“ื™ ืคืึทืจื˜ื™ืง ื‘ื™ืœื“ ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขืคึฟื•ื ืขืŸ ื“ืึธ: https://hub.docker.com/r/alexxxnf/spa-builder. ื›ืึธื˜ืฉ ืื™ืš ืจืขืงืึธืžืขื ื“ื™ืจืŸ ื ื™ืฉื˜ ืคืึทืจืœืึธื–ื  ืื•ื™ืฃ ืื ื“ืขืจืข ืžืขื ื˜ืฉืŸ ืก ื‘ื™ืœื“ืขืจ ืื•ืŸ ืงืึทืœืขืงื˜ื™ื ื’ ื“ื™ื™ืŸ ืื™ื™ื’ืขื ืข.

ื ื’ื™ื ืงืก

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

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

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

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

ืœืขืจื ืขืŸ ืกื˜ืึทื˜ื™ืงืก ืฆื• ืคึฟืึทืจืฉื˜ื™ื™ืŸ ืกื•ื•ื™ื•ื•ืข ื•ื•ืขืจื™ืึทื‘ืึทืœื–

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

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

ืคึฟืึทืจ ื“ืขื ืฆื•ื•ืขืง, ื“ื™ Dockerfile ื’ื™ื˜ ื“ื™ 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}.

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

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

ืึทืกืขืžื‘ืึทืœ ื“ื™ ืœืขืฆื˜ ื‘ื™ืœื“

ืฆื•ื ืกื•ืฃ.

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