Π”ΠΎΠΊΠ΅Ρ€ слика Π·Π° Π΄ΠΈΡΡ‚Ρ€ΠΈΠ±ΡƒΡ†ΠΈΡ˜Π° Π½Π° Π°ΠΏΠ»ΠΈΠΊΠ°Ρ†ΠΈΡ˜Π° Π·Π° Π΅Π΄Π½Π° страница

ΠΠΏΠ»ΠΈΠΊΠ°Ρ†ΠΈΡ˜Π° со Π΅Π΄Π½Π° страница (SPA) Π΅ Π·Π±ΠΈΡ€ Π½Π° статични JavaScript ΠΈ HTML Π΄Π°Ρ‚ΠΎΡ‚Π΅ΠΊΠΈ, ΠΊΠ°ΠΊΠΎ ΠΈ слики ΠΈ Π΄Ρ€ΡƒΠ³ΠΈ рСсурси. Π‘ΠΈΠ΄Π΅Ρ˜ΡœΠΈ Ρ‚ΠΈΠ΅ Π½Π΅ сС ΠΌΠ΅Π½ΡƒΠ²Π°Π°Ρ‚ Π΄ΠΈΠ½Π°ΠΌΠΈΡ‡Π½ΠΎ, Π½ΠΈΠ²Π½ΠΎΡ‚ΠΎ ΠΎΠ±Ρ˜Π°Π²ΡƒΠ²Π°ΡšΠ΅ Π½Π° ΠΈΠ½Ρ‚Π΅Ρ€Π½Π΅Ρ‚ Π΅ ΠΌΠ½ΠΎΠ³Ρƒ лСсно. Има Π³ΠΎΠ»Π΅ΠΌ Π±Ρ€ΠΎΡ˜ Π½Π° Π΅Π²Ρ‚ΠΈΠ½ΠΈ, ΠΏΠ° Π΄ΡƒΡ€ΠΈ ΠΈ бСсплатни услуги Π·Π° ΠΎΠ²Π°, ΠΏΠΎΡ‡Π½ΡƒΠ²Π°Ρ˜ΡœΠΈ ΠΎΠ΄ Сдноставни GitHub Pages (Π° Π·Π° Π½Π΅ΠΊΠΎΠΈ Π΄ΡƒΡ€ΠΈ ΠΈ со narod.ru) ΠΈ Π·Π°Π²Ρ€ΡˆΡƒΠ²Π°Ρ˜ΡœΠΈ со CDN ΠΊΠ°ΠΊΠΎ Amazon S3. Π‘Π΅ΠΏΠ°ΠΊ, ΠΌΠΈ Ρ‚Ρ€Π΅Π±Π°ΡˆΠ΅ Π½Π΅ΡˆΡ‚ΠΎ Π΄Ρ€ΡƒΠ³ΠΎ.

Ми Ρ‚Ρ€Π΅Π±Π°ΡˆΠ΅ Docker слика со SPA Π·Π° Π΄Π° ΠΌΠΎΠΆΠ΅ лСсно Π΄Π° сС лансира ΠΈ Π²ΠΎ производство ΠΊΠ°ΠΊΠΎ Π΄Π΅Π» ΠΎΠ΄ кластСрот Kubernetes ΠΈ Π½Π° ΠΌΠ°ΡˆΠΈΠ½Π°Ρ‚Π° Π½Π° back-end ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ΅Ρ€ кој Π½Π΅ΠΌΠ° ΠΏΠΎΠΈΠΌ ΡˆΡ‚ΠΎ Π΅ SPA.

Π“ΠΈ ΠΎΠ΄Ρ€Π΅Π΄ΠΈΠ² слСднитС Π±Π°Ρ€Π°ΡšΠ° Π·Π° слика Π·Π° сСбС:

  • Π»Π΅ΡΠ½ΠΎΡ‚ΠΈΡ˜Π° Π½Π° ΠΊΠΎΡ€ΠΈΡΡ‚Π΅ΡšΠ΅ (Π½ΠΎ Π½Π΅ ΠΈ ΡΠΊΠ»ΠΎΠΏΡƒΠ²Π°ΡšΠ΅);
  • ΠΌΠΈΠ½ΠΈΠΌΠ°Π»Π½Π° Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π° ΠΈ Π²ΠΎ однос Π½Π° дискот ΠΈ RAM ΠΌΠ΅ΠΌΠΎΡ€ΠΈΡ˜Π°Ρ‚Π°;
  • ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ˜Π° ΠΏΡ€Π΅ΠΊΡƒ ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° ΠΆΠΈΠ²ΠΎΡ‚Π½Π°Ρ‚Π° срСдина, Ρ‚Π°ΠΊΠ° ΡˆΡ‚ΠΎ сликата ΠΌΠΎΠΆΠ΅ Π΄Π° сС користи Π²ΠΎ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ срСдини;
  • Π½Π°Ρ˜Π΅Ρ„ΠΈΠΊΠ°ΡΠ½Π° Π΄ΠΈΡΡ‚Ρ€ΠΈΠ±ΡƒΡ†ΠΈΡ˜Π° Π½Π° Π΄Π°Ρ‚ΠΎΡ‚Π΅ΠΊΠΈ.

ДСнСс ќС Π²ΠΈ ΠΊΠ°ΠΆΠ°ΠΌ ΠΊΠ°ΠΊΠΎ:

  • Ρ†Ρ€Π΅Π²Π½Π° нгинкс;
  • ΠΈΠ·Π³Ρ€Π°Π΄ΠΈ Π±Ρ€ΠΎΡ‚Π»ΠΈ ΠΎΠ΄ ΠΈΠ·Π²ΠΎΡ€ΠΈ;
  • ΡƒΡ‡Π°Ρ‚ статички Π΄Π°Ρ‚ΠΎΡ‚Π΅ΠΊΠΈ Π΄Π° Π³ΠΈ Ρ€Π°Π·Π±Π΅Ρ€Π°Ρ‚ ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈΡ‚Π΅ Π½Π° ΠΎΠΊΠΎΠ»ΠΈΠ½Π°Ρ‚Π°;
  • ΠΈ сСкако ΠΊΠ°ΠΊΠΎ Π΄Π° сС состави Docker слика ΠΎΠ΄ сСто ΠΎΠ²Π°.

Π¦Π΅Π»Ρ‚Π° Π½Π° ΠΎΠ²Π°Π° ΡΡ‚Π°Ρ‚ΠΈΡ˜Π° Π΅ Π΄Π° Π³ΠΎ сподСлам ΠΌΠΎΠ΅Ρ‚ΠΎ искуство ΠΈ Π΄Π° Π³ΠΈ ΠΏΠΎΡ‚Ρ‚ΠΈΠΊΠ½Π°ΠΌ искуснитС Ρ‡Π»Π΅Π½ΠΎΠ²ΠΈ Π½Π° Π·Π°Π΅Π΄Π½ΠΈΡ†Π°Ρ‚Π° Π½Π° конструктивна ΠΊΡ€ΠΈΡ‚ΠΈΠΊΠ°.

Π˜Π·Π³Ρ€Π°Π΄Π±Π° Π½Π° слика Π·Π° ΡΠΊΠ»ΠΎΠΏΡƒΠ²Π°ΡšΠ΅

Π—Π° Π΄Π° ја Π½Π°ΠΏΡ€Π°Π²ΠΈΡ‚Π΅ ΠΊΠΎΠ½Π΅Ρ‡Π½Π°Ρ‚Π° слика Π½Π° 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

Π’Π΅ΡœΠ΅ ΠΎΠ²Π΄Π΅ сС Π±ΠΎΡ€Π°ΠΌ Π·Π° ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΠΈΠ·Π°ΠΌ, ΠΏΠ° сликата ја составува Π΅Π΄Π΅Π½ Π³ΠΎΠ»Π΅ΠΌ Ρ‚ΠΈΠΌ.

Π“ΠΎΡ‚ΠΎΠ²Π°Ρ‚Π° слика ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ја Π½Π°Ρ˜Π΄Π΅Ρ‚Π΅ ΠΎΠ²Π΄Π΅: https://hub.docker.com/r/alexxxnf/spa-builder. Иако ΠΏΡ€Π΅ΠΏΠΎΡ€Π°Ρ‡ΡƒΠ²Π°ΠΌ Π΄Π° Π½Π΅ сС ΠΏΠΎΡ‚ΠΏΠΈΡ€Π°Ρ‚Π΅ Π½Π° Ρ‚ΡƒΡ“ΠΈΡ‚Π΅ слики ΠΈ Π΄Π° собиратС свои.

nginx

ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° користитС кој Π±ΠΈΠ»ΠΎ Π²Π΅Π±-сСрвСр Π·Π° Π΄Π° дистрибуиратС статична содрТина. Навикнат сум Π΄Π° Ρ€Π°Π±ΠΎΡ‚Π°ΠΌ со nginx, ΠΏΠ° ќС Π³ΠΎ користам сСга.

Nginx ΠΈΠΌΠ° ΠΎΡ„ΠΈΡ†ΠΈΡ˜Π°Π»Π½Π° слика Π½Π° Docker, Π½ΠΎ ΠΈΠΌΠ° ΠΏΡ€Π΅ΠΌΠ½ΠΎΠ³Ρƒ ΠΌΠΎΠ΄ΡƒΠ»ΠΈ Π·Π° Сдноставна статичка Π΄ΠΈΡΡ‚Ρ€ΠΈΠ±ΡƒΡ†ΠΈΡ˜Π°. Кои ΠΎΠ΄ Π½ΠΈΠ² сС Π²ΠΊΠ»ΡƒΡ‡Π΅Π½ΠΈ Π²ΠΎ испораката ΠΌΠΎΠΆΠ΅ Π΄Π° сС Π²ΠΈΠ΄ΠΈ ΠΎΠ΄ ΡΠΏΠ΅Ρ†ΠΈΡ˜Π°Π»Π΅Π½ Ρ‚ΠΈΠΌ ΠΈΠ»ΠΈ Π²ΠΎ ΠΎΡ„ΠΈΡ†ΠΈΡ˜Π°Π»Π½ΠΈΠΎΡ‚ Dockerfile.

$ docker run --rm nginx:1-алпски 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, кој Π΅ ΠΌΠ°Π»ΠΊΡƒ поСфикасСн ΠΎΠ΄ 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 ΠΈ Π΄Π° сС ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π° ΠΊΠΎΠ»ΠΊΡƒ ΡˆΡ‚ΠΎ Π΅ ΠΏΠΎΡ‚Ρ€Π΅Π±Π½ΠΎ Π²ΠΎ Ρ„Π°Π·Π°Ρ‚Π° Π½Π° Π¦Π” ΠΊΠΎΡ€ΠΈΡΡ‚Π΅Ρ˜ΡœΠΈ ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° ΠΎΠΊΠΎΠ»ΠΈΠ½Π°Ρ‚Π°.

Π‘Π΅ Ρ€Π°Π·Π±ΠΈΡ€Π°, самитС статични Π΄Π°Ρ‚ΠΎΡ‚Π΅ΠΊΠΈ Π½Π΅ Ρ€Π°Π·Π±ΠΈΡ€Π°Π°Ρ‚ Π½ΠΈΠΊΠ°ΠΊΠ²ΠΈ ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° ΠΎΠΊΠΎΠ»ΠΈΠ½Π°Ρ‚Π°. Π—Π°Ρ‚ΠΎΠ°, ќС ΠΌΠΎΡ€Π° Π΄Π° ΡƒΠΏΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅ Ρ‚Ρ€ΠΈΠΊ. На послСдната слика, Π½Π΅ΠΌΠ° Π΄Π° стартувам nginx, Ρ‚ΡƒΠΊΡƒ ΡΠΏΠ΅Ρ†ΠΈΡ˜Π°Π»Π½Π° скрипта Π·Π° школка која ќС Ρ‡ΠΈΡ‚Π° ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° ΠΎΠΊΠΎΠ»ΠΈΠ½Π°Ρ‚Π°, ќС Π³ΠΈ Π·Π°ΠΏΠΈΡˆΡƒΠ²Π° Π²ΠΎ статични Π΄Π°Ρ‚ΠΎΡ‚Π΅ΠΊΠΈ, ќС Π³ΠΈ компрСсира ΠΈ Π΄ΡƒΡ€ΠΈ ΠΏΠΎΡ‚ΠΎΠ° ќС ја ΠΏΡ€Π΅Ρ„Ρ€Π»ΠΈ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π°Ρ‚Π° Π½Π° nginx.

Π—Π° Ρ‚Π°Π° Ρ†Π΅Π», Dockerfile Π³ΠΎ ΠΎΠ±Π΅Π·Π±Π΅Π΄ΡƒΠ²Π° ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Π°Ρ€ΠΎΡ‚ ENTRYPOINT. АјдС Π΄Π° ΠΌΡƒ ја Π΄Π°Π΄Π΅ΠΌΠ΅ слСдната скрипта (ΠΊΠΎΡ€ΠΈΡΡ‚Π΅Ρ˜ΡœΠΈ Π³ΠΎ Angular ΠΊΠ°ΠΊΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€):

Π΄ΠΎΠΊΠ΅Ρ€-Π²Π»Π΅Π·Π½Π° Ρ‚ΠΎΡ‡ΠΊΠ°.ш

#!/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