ΠΠ΄Π½ΠΎΡΡΡΠ°Π½ΠΈΡΠ½ΠΎΡΠΎ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ (SPA) Π΅ Π½Π°Π±ΠΎΡ ΠΎΡ ΡΡΠ°ΡΠΈΡΠ½ΠΈ JavaScript ΠΈ HTML ΡΠ°ΠΉΠ»ΠΎΠ²Π΅, ΠΊΠ°ΠΊΡΠΎ ΠΈ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ ΠΈ Π΄ΡΡΠ³ΠΈ ΡΠ΅ΡΡΡΡΠΈ. Π’ΡΠΉ ΠΊΠ°ΡΠΎ ΡΠ΅ Π½Π΅ ΡΠ΅ ΠΏΡΠΎΠΌΠ΅Π½ΡΡ Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ½ΠΎ, ΠΏΡΠ±Π»ΠΈΠΊΡΠ²Π°Π½Π΅ΡΠΎ ΠΈΠΌ Π² ΠΈΠ½ΡΠ΅ΡΠ½Π΅Ρ Π΅ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΡΠΎΡΡΠΎ. ΠΠ° ΡΠ΅Π»ΡΠ° ΡΡΡΠ΅ΡΡΠ²ΡΠ²Π° Π³ΠΎΠ»ΡΠΌΠΎ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ Π΅Π²ΡΠΈΠ½ΠΈ ΠΈ Π΄ΠΎΡΠΈ Π±Π΅Π·ΠΏΠ»Π°ΡΠ½ΠΈ ΡΡΠ»ΡΠ³ΠΈ, Π·Π°ΠΏΠΎΡΠ²Π°ΠΉΠΊΠΈ ΠΎΡ ΠΏΡΠΎΡΡΠΈΡ GitHub Pages (Π° Π·Π° Π½ΡΠΊΠΎΠΈ Π΄ΠΎΡΠΈ ΠΎΡ narod.ru) ΠΈ ΡΡΠΈΠ³Π°ΠΉΠΊΠΈ Π΄ΠΎ CDN ΠΊΠ°ΡΠΎ Amazon S3. ΠΠΎ Π°Π· ΡΠ΅ Π½ΡΠΆΠ΄Π°Π΅Ρ ΠΎΡ Π½Π΅ΡΠΎ ΡΠ°Π·Π»ΠΈΡΠ½ΠΎ.
Π’ΡΡΠ±Π²Π°ΡΠ΅ ΠΌΠΈ Docker ΠΎΠ±ΡΠ°Π· Ρ SPA, Π·Π° Π΄Π° ΠΌΠΎΠΆΠ΅ Π»Π΅ΡΠ½ΠΎ Π΄Π° Π±ΡΠ΄Π΅ ΡΡΠ°ΡΡΠΈΡΠ°Π½ ΠΊΠ°ΠΊΡΠΎ Π² ΠΏΡΠΎΠ΄ΡΠΊΡΠΈΡ Π² ΡΡΡΡΠ°Π²Π° Π½Π° Kubernetes ΠΊΠ»ΡΡΡΠ΅ΡΠ°, ΡΠ°ΠΊΠ° ΠΈ Π½Π° ΠΌΠ°ΡΠΈΠ½Π°ΡΠ° Π½Π° back-end ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°, ΠΊΠΎΠΉΡΠΎ Π½ΡΠΌΠ° ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π° ΠΊΠ°ΠΊΠ²ΠΎ Π΅ SPA.
ΠΠΏΡΠ΅Π΄Π΅Π»ΠΈΡ ΡΠ»Π΅Π΄Π½ΠΈΡΠ΅ ΠΈΠ·ΠΈΡΠΊΠ²Π°Π½ΠΈΡ Π·Π° ΠΎΠ±ΡΠ°Π·Π°:
- Π»Π΅ΡΠ΅Π½ Π·Π° ΡΠΏΠΎΡΡΠ΅Π±Π° (Π½ΠΎ Π½Π΅ ΠΏΠΎ Π²ΡΠ΅ΠΌΠ΅ Π½Π° ΠΈΠ·Π³ΡΠ°ΠΆΠ΄Π°Π½Π΅);
- ΠΌΠΈΠ½ΠΈΠΌΠ°Π»Π΅Π½ ΡΠ°Π·ΠΌΠ΅Ρ ΠΊΠ°ΠΊΡΠΎ ΠΏΠΎ ΠΎΡΠ½ΠΎΡΠ΅Π½ΠΈΠ΅ Π½Π° Π΄ΠΈΡΠΊΠ°, ΡΠ°ΠΊΠ° ΠΈ ΠΏΠΎ ΠΎΡΠ½ΠΎΡΠ΅Π½ΠΈΠ΅ Π½Π° RAM;
- ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ ΡΡΠ΅Π· ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° ΡΡΠ΅Π΄Π°ΡΠ°, ΡΠ°ΠΊΠ° ΡΠ΅ ΠΎΠ±ΡΠ°Π·ΡΡ Π΄Π° ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π² ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ ΡΡΠ΅Π΄ΠΈ;
- ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»Π½ΠΎ Π΅ΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎ ΡΠ°Π·ΠΏΡΠΎΡΡΡΠ°Π½Π΅Π½ΠΈΠ΅ Π½Π° ΡΠ°ΠΉΠ»ΠΎΠ²Π΅.
ΠΠ½Π΅Ρ ΡΠ΅ Π²ΠΈ ΡΠ°Π·ΠΊΠ°ΠΆΠ° ΠΊΠ°ΠΊ:
- Π΄Π° ΠΈΠ·Π²Π»Π΅ΠΊΠ° nginx;
- Π΄Π° ΡΡΠ±Π΅ΡΠ° brotli ΠΎΡ ΠΈΠ·Ρ ΠΎΠ΄Π½ΠΈΡ ΠΊΠΎΠ΄;
- Π΄Π° Π½Π°ΡΡΠ° ΡΡΠ°ΡΠΈΡΠ½ΠΈΡΠ΅ ΡΠ°ΠΉΠ»ΠΎΠ²Π΅ Π΄Π° ΡΠ°Π·Π±ΠΈΡΠ°Ρ ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° ΡΡΠ΅Π΄Π°ΡΠ°;
- ΠΈ, ΡΠ°Π·Π±ΠΈΡΠ° ΡΠ΅, ΠΊΠ°ΠΊ Π΄Π° ΡΡΡΡΠ°Π²Ρ ΠΎΡ Π²ΡΠΈΡΠΊΠΎ ΡΠΎΠ²Π° Docker ΠΎΠ±ΡΠ°Π·.
Π¦Π΅Π»ΡΠ° Π½Π° ΡΠ°Π·ΠΈ ΡΡΠ°ΡΠΈΡ Π΅ Π΄Π° ΡΠΏΠΎΠ΄Π΅Π»ΠΈ ΠΌΠΎΡΡ ΠΎΠΏΠΈΡ ΠΈ Π΄Π° ΠΏΡΠ΅Π΄ΠΈΠ·Π²ΠΈΠΊΠ° ΠΎΠΏΠΈΡΠ½ΠΈ ΡΡΠ°ΡΡΠ½ΠΈΡΠΈ Π² ΠΎΠ±ΡΠ½ΠΎΡΡΡΠ° Π½Π° ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΈΠ²Π½Π° ΠΊΡΠΈΡΠΈΠΊΠ°.
Π‘Π³Π»ΠΎΠ±ΡΠ²Π°Π½Π΅ Π½Π° ΠΎΠ±ΡΠ°Π· Π·Π° ΠΈΠ·Π³ΡΠ°ΠΆΠ΄Π°Π½Π΅
ΠΠ° Π΄Π° Π±ΡΠ΄Π΅ ΡΠΈΠ½Π°Π»Π½ΠΈΡΡ Docker ΠΎΠ±ΡΠ°Π· ΠΌΠ°Π»ΡΠΊ ΠΏΠΎ ΡΠ°Π·ΠΌΠ΅Ρ, ΡΡΡΠ±Π²Π° Π΄Π° ΡΠ΅ ΡΠΏΠ°Π·Π²Π°Ρ Π΄Π²Π΅ ΠΏΡΠ°Π²ΠΈΠ»Π°: ΠΌΠΈΠ½ΠΈΠΌΡΠΌ ΡΠ»ΠΎΠ΅Π²Π΅ ΠΈ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΠΈΡΡΠΈΡΠ΅Π½ Π±Π°Π·ΠΎΠ² ΠΎΠ±ΡΠ°Π·. ΠΠ΄ΠΈΠ½ ΠΎΡ Π½Π°ΠΉ-ΠΌΠ°Π»ΠΊΠΈΡΠ΅ Π±Π°Π·ΠΎΠ²ΠΈ ΠΎΠ±ΡΠ°Π·ΠΈ Π΅ ΠΎΠ±ΡΠ°Π·ΡΡ Alpine Linux, Π·Π°ΡΠΎΠ²Π° ΠΈΠΌΠ΅Π½Π½ΠΎ Π½Π΅Π³ΠΎ ΡΠ΅ ΠΈΠ·Π±Π΅ΡΠ°. ΠΡΠΊΠΎΠΉ ΠΌΠΎΠΆΠ΅ Π΄Π° Π²ΡΠ·ΡΠ°Π·ΠΈ, ΡΠ΅ Alpine Π½Π΅ Π΅ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ΡΡ Π·Π° ΠΏΡΠΎΠ΄ΡΠΊΡΠΈΡ ΠΈ Π²Π΅ΡΠΎΡΡΠ½ΠΎ ΡΠ΅ Π±ΡΠ΄Π΅ ΠΏΡΠ°Π². ΠΠΎ Π»ΠΈΡΠ½ΠΎ Π°Π· Π½ΠΈΠΊΠΎΠ³Π° Π½Π΅ ΡΡΠΌ ΠΈΠΌΠ°Π» ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ Ρ Π½Π΅Π³ΠΎ ΠΈ Π½ΡΠΌΠ°ΠΌ Π°ΡΠ³ΡΠΌΠ΅Π½ΡΠΈ ΡΡΠ΅ΡΡ Π½Π΅Π³ΠΎ.
ΠΠ° Π΄Π° ΠΈΠΌΠ° ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΎ ΡΠ»ΠΎΠ΅Π²Π΅, ΡΠ΅ ΠΈΠ·Π³ΡΠ°ΠΆΠ΄Π°ΠΌ ΠΎΠ±ΡΠ°Π·Π° Π½Π° 2 Π΅ΡΠ°ΠΏΠ°. ΠΡΡΠ²ΠΈΡΡ β ΡΠ΅ΡΠ½ΠΎΠ²ΠΈ, Π² Π½Π΅Π³ΠΎ ΡΠ΅ ΠΎΡΡΠ°Π½Π°Ρ Π²ΡΠΈΡΠΊΠΈ ΠΏΠΎΠΌΠΎΡΠ½ΠΈ ΡΡΠΈΠ»ΠΈΡΠΈ ΠΈ Π²ΡΠ΅ΠΌΠ΅Π½Π½ΠΈ ΡΠ°ΠΉΠ»ΠΎΠ²Π΅. Π Π² ΡΠΈΡΡΠΎΠ²ΠΈΡ ΡΠ΅ Π·Π°ΠΏΠΈΡΠ° ΡΠ°ΠΌΠΎ ΡΠΈΠ½Π°Π»Π½Π°ΡΠ° Π²Π΅ΡΡΠΈΡ Π½Π° ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΡΠΎ.
ΠΠ΅ΠΊΠ° Π·Π°ΠΏΠΎΡΠ½Π΅ΠΌ Ρ ΠΏΠΎΠΌΠΎΡΠ½ΠΈΡ ΠΎΠ±ΡΠ°Π·.
ΠΠ° Π΄Π° ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡΠ°ΠΌΠ΅ SPA ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΡΠΎ, ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ Π΅ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌ node.js. Π©Π΅ Π²Π·Π΅ΠΌΠ° ΠΎΡΠΈΡΠΈΠ°Π»Π½ΠΈΡ ΠΎΠ±ΡΠ°Π·, Π² ΠΊΠΎΠΌΠΏΠ»Π΅ΠΊΡ Ρ ΠΊΠΎΠΉΡΠΎ ΠΈΠΌΠ° ΠΈ ΠΏΠ°ΠΊΠ΅ΡΠ½ΠΈ ΠΌΠ΅Π½ΠΈΠ΄ΠΆΡΡΠΈ npm ΠΈ yarn. ΠΡ ΡΠ΅Π±Π΅ ΡΠΈ ΡΠ΅ Π΄ΠΎΠ±Π°Π²Ρ node-gyp, ΠΊΠΎΠΉΡΠΎ Π΅ Π½ΡΠΆΠ΅Π½ Π·Π° ΠΈΠ·Π³ΡΠ°ΠΆΠ΄Π°Π½Π΅ Π½Π° Π½ΡΠΊΠΎΠΈ npm ΠΏΠ°ΠΊΠ΅ΡΠΈ, ΠΈ ΠΊΠΎΠΌΠΏΡΠ΅ΡΠΎΡ Brotli ΠΎΡ Google, ΠΊΠΎΠΉΡΠΎ ΡΠ΅ Π½ΠΈ Π΅ ΠΏΠΎΠ»Π΅Π·Π΅Π½ ΠΏΠΎ-ΠΊΡΡΠ½ΠΎ.
Dockerfile Ρ ΠΊΠΎΠΌΠ΅Π½ΡΠ°ΡΠΈ.
# ΠΠ°Π·ΠΎΠ²ΡΠΉ ΠΎΠ±ΡΠ°Π·
FROM node:12-alpine
LABEL maintainer="Aleksey Maydokin <amaydokin@gmail.com>"
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ΠΠ΅ΡΠ΅ ΡΡΠΊ ΡΠ΅ Π±ΠΎΡΡ Π·Π° ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΠΈΠ·ΡΠΌ, Π·Π°ΡΠΎΠ²Π° ΠΎΠ±ΡΠ°Π·ΡΡ ΡΠ΅ ΠΈΠ·Π³ΡΠ°ΠΆΠ΄Π° Ρ Π΅Π΄Π½Π° Π³ΠΎΠ»ΡΠΌΠ° ΠΊΠΎΠΌΠ°Π½Π΄Π°.
ΠΠΎΡΠΎΠ²ΠΈΡΡ ΠΎΠ±ΡΠ°Π· ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ Π½Π°ΠΌΠ΅ΡΠΈ ΡΡΠΊ: . ΠΡΠΏΡΠ΅ΠΊΠΈ ΡΠΎΠ²Π°, ΠΏΡΠ΅ΠΏΠΎΡΡΡΠ²Π°ΠΌ Π΄Π° Π½Π΅ ΡΠ°Π·ΡΠΈΡΠ°ΡΠ΅ Π½Π° Π³ΠΎΡΠΎΠ²ΠΈ ΠΎΠ±ΡΠ°Π·ΠΈ ΠΈ Π΄Π° ΡΡΠ±Π΅ΡΠ΅ΡΠ΅ ΡΠ²ΠΎΠΉ ΡΠΎΠ±ΡΡΠ²Π΅Π½.
nginx
ΠΠ° ΡΠ°Π·ΠΏΡΠΎΡΡΡΠ°Π½Π΅Π½ΠΈΠ΅ Π½Π° ΡΡΠ°ΡΠΈΡΠ½ΠΈ ΡΠ°ΠΉΠ»ΠΎΠ²Π΅ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ Π²ΡΠ΅ΠΊΠΈ web-ΡΠ΅ΡΠ²Π΅Ρ. ΠΠ· ΠΈΠΌΠ°ΠΌ Π½Π°Π²ΠΈΠΊΠ° Π΄Π° ΡΠ°Π±ΠΎΡΡ Ρ 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, ΠΊΠΎΠΉΡΠΎ Π΅ ΠΌΠ°Π»ΠΊΠΎ ΠΏΠΎ-Π΅ΡΠ΅ΠΊΡΠΈΠ²Π΅Π½ ΠΎΡ gzip. Π©Π΅ ΠΊΠΎΠΌΠΏΡΠ΅ΡΠΈΡΠ°ΠΌΠ΅ ΡΠ°ΠΉΠ»ΠΎΠ²Π΅ΡΠ΅ ΡΠ°ΠΌΠΎ Π²Π΅Π΄Π½ΡΠΆ, Π½Π΅ Π΅ Π½ΡΠΆΠ½ΠΎ Π΄Π° Π³ΠΎ ΠΏΡΠ°Π²ΠΈΠΌ Π½Π° Π»Π΅ΡΠ΅ΠΆ.
ΠΡΠΎ ΠΊΠ°ΠΊΡΠ² Dockerfile ΠΏΠΎΠ»ΡΡΠΈΡ . ΠΠΎΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ΅ Π½Π° ΡΡΡΠΊΠΈ β ΠΌΠΎΠΈ, Π½Π° Π°Π½Π³Π»ΠΈΠΉΡΠΊΠΈ β ΠΎΡ ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»Π°.
Dockerfile
# ΠΠ°Π·ΠΎΠ²ΡΠΉ ΠΎΠ±ΡΠ°Π· ΡΠ½ΠΎΠ²Π° Alpine
FROM alpine:3.9
LABEL maintainer="Aleksey Maydokin <amaydokin@gmail.com>"
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";
}
}
}
}ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΈΠ·ΡΠ΅Π³Π»ΠΈΡΠ΅ Π³ΠΎΡΠΎΠ²ΠΈΡ ΠΎΠ±ΡΠ°Π· ΡΡΠΊ: . ΠΠ°Π΅ΡΠΎ Π΅ 10,5 MB. ΠΡΠΈΠ³ΠΈΠ½Π°Π»Π½ΠΈΡΡ nginx Π·Π°Π΅ΠΌΠ° 19,7 MB. Π£Π΄ΠΎΠ²Π»Π΅ΡΠ²ΠΎΡΠΈΡ ΡΠΏΠΎΡΡΠ½ΠΈΡ ΡΠΈ ΠΈΠ½ΡΠ΅ΡΠ΅Ρ.
Π£ΡΠΈΠΌ ΡΡΠ°ΡΠΈΡΠ½ΠΎΡΠΎ Π΄Π° ΡΠ°Π·Π±ΠΈΡΠ° ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° ΡΡΠ΅Π΄Π°ΡΠ°
ΠΠ° ΠΊΠ°ΠΊΠ²ΠΎ ΡΠ° Π½ΡΠΆΠ½ΠΈ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈΡΠ΅ Π² SPA? ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π·Π° Π΄Π° ΡΠΊΠ°ΠΆΠ΅ΠΌ ΠΊΠΎΠΉ RESTful API Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅. ΠΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈΡΠ΅ Π·Π° Π½ΡΠΆΠ½Π°ΡΠ° ΡΡΠ΅Π΄Π° ΡΠ΅ ΠΏΡΠ΅Π΄Π°Π²Π°Ρ Π½Π° SPA ΠΏΠΎ Π²ΡΠ΅ΠΌΠ΅ Π½Π° ΡΠ³Π»ΠΎΠ±ΡΠ²Π°Π½Π΅ΡΠΎ. ΠΠΊΠΎ ΡΡΡΠ±Π²Π° Π½Π΅ΡΠΎ Π΄Π° ΠΏΡΠΎΠΌΠ΅Π½ΠΈΠΌ, ΡΠ΅ ΡΡΡΠ±Π²Π° Π΄Π° ΠΏΡΠ΅Π³ΡΡΠΏΠΈΡΠ°ΠΌΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΡΠΎ. ΠΠ΅ ΠΈΡΠΊΠ°ΠΌ ΡΠΎΠ²Π°. ΠΡΠΊΠ°ΠΌ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΡΠΎ Π΄Π° ΡΠ΅ ΡΠ³Π»ΠΎΠ±ΡΠ²Π° Π²Π΅Π΄Π½ΡΠΆ Π½Π° Π΅ΡΠ°ΠΏ CI, Π° Π΄Π° ΡΠ΅ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠΈΡΠ° ΡΠΎΠ»ΠΊΠΎΠ²Π°, ΠΊΠΎΠ»ΠΊΠΎΡΠΎ Π΅ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ, Π½Π° Π΅ΡΠ°ΠΏ CD Ρ ΠΏΠΎΠΌΠΎΡΡΠ° Π½Π° ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° ΡΡΠ΅Π΄Π°ΡΠ°.
Π Π°Π·Π±ΠΈΡΠ° ΡΠ΅, ΡΡΠ°ΡΠΈΡΠ½ΠΈΡΠ΅ ΡΠ°ΠΉΠ»ΠΎΠ²Π΅ ΡΠ°ΠΌΠΈ ΠΏΠΎ ΡΠ΅Π±Π΅ ΡΠΈ Π½Π΅ ΡΠ°Π·Π±ΠΈΡΠ°Ρ Π½ΠΈΠΊΠ°ΠΊΠ²ΠΈ ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° ΡΡΠ΅Π΄Π°ΡΠ°. ΠΠ°ΡΠΎΠ²Π° ΡΠ΅ ΡΡΡΠ±Π²Π° Π΄Π° ΠΏΡΠΈΠ±Π΅Π³Π½Π΅ΠΌ Π΄ΠΎ Ρ ΠΈΡΡΠΎΡΡ. Π ΠΊΡΠ°ΠΉΠ½ΠΈΡ ΠΎΠ±ΡΠ°Π· ΡΠ΅ ΡΡΠ°ΡΡΠΈΡΠ°ΠΌ Π½Π΅ 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-ΡΠ°ΠΉΠ»Π°Ρ
Π·Π° f Π² "$TARGET_DIR"/main*.js; Π½Π°ΠΏΡΠ°Π²ΠΈ
# envsubst Π·Π°ΠΌΠ΅Π½ΡΠ΅Ρ Π² ΡΠ°ΠΉΠ»Π°Ρ ΠΏΠ»Π΅ΠΉΡΡ ΠΎΠ»Π΄Π΅ΡΡ Π½Π° Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΈΠ· ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ
echo "$(envsubst "$ENV_VARS" "$f"
Π³ΠΎΡΠΎΠ²ΠΎ
}
ΠΊΠΎΠΌΠΏΡΠ΅Ρ () {
for i in $(find "$TARGET_DIR" | grep -E ".css$|.html$|.js$|.svg$|.txt$|.ttfquot;); Π½Π°ΠΏΡΠ°Π²ΠΈ
# ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΡΡ ΡΡΠ΅ΠΏΠ΅Π½Ρ ΡΠΆΠ°ΡΠΈΡ
gzip -9kf "$i" && brotli -fZ "$i"
Π³ΠΎΡΠΎΠ²ΠΎ
}
Π°ΠΊΠΎ [ "$1" = 'nginx' ]; ΡΠΎΠ³Π°Π²Π°
# Π€Π»Π°Π³ Π½ΡΠΆΠ΅Π½, ΡΡΠΎΠ±Ρ Π²ΡΠΏΠΎΠ»Π½ΠΈΡΡ ΡΠΊΡΠΈΠΏΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΡΠΈ ΡΠ°ΠΌΠΎΠΌ ΠΏΠ΅ΡΠ²ΠΎΠΌ Π·Π°ΠΏΡΡΠΊΠ΅
Π°ΠΊΠΎ [ ! -e "$FLAG_FILE" ]; ΡΠΎΠ³Π°Π²Π°
echo "Π‘ΡΠ°ΡΡΠΈΡΠ°Π½Π΅ Π½Π° ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΎΠ½Π½ΠΈΡ ΡΠΊΡΠΈΠΏΡ"
echo "ΠΠ°ΠΌΡΠ½Π° Π½Π° ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° ΡΡΠ΅Π΄Π°ΡΠ°"
replace_vars
echo "ΠΠΎΠΌΠΏΡΠ΅ΡΠΈΡΠ°Π½Π΅ Π½Π° ΡΠ°ΠΉΠ»ΠΎΠ²Π΅"
ΠΊΠΎΠΌΠΏΡΠ΅Ρ
touch $FLAG_FILE
echo "ΠΠΎΡΠΎΠ²ΠΎ"
ΡΠΈ
ΡΠΈ
exec "$@"
ΠΠ° Π΄Π° ΠΌΠΎΠΆΠ΅ ΡΠΊΡΠΈΠΏΡΡΡ Π΄Π° ΡΠ²ΡΡΡΠΈ ΡΠ°Π±ΠΎΡΠ°ΡΠ° ΡΠΈ, Π² js ΡΠ°ΠΉΠ»ΠΎΠ²Π΅ΡΠ΅ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈΡΠ΅ ΡΡΡΠ±Π²Π° Π΄Π° Π±ΡΠ΄Π°Ρ Π·Π°ΠΏΠΈΡΠ°Π½ΠΈ ΠΏΠΎ ΡΠ»Π΅Π΄Π½ΠΈΡ Π½Π°ΡΠΈΠ½:${API_URL}.Π‘ΡΡΡΠ²Π° ΡΠΈ Π΄Π° ΡΠ΅ ΠΎΡΠ±Π΅Π»Π΅ΠΆΠΈ, ΡΠ΅ ΠΏΠΎΠ²Π΅ΡΠ΅ΡΠΎ ΡΡΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΈ SPA ΠΏΡΠΈ ΡΠ³Π»ΠΎΠ±ΡΠ²Π°Π½Π΅ Π΄ΠΎΠ±Π°Π²ΡΡ Ρ Π΅ΡΠΎΠ²Π΅ ΠΊΡΠΌ ΡΠ°ΠΉΠ»ΠΎΠ²Π΅ΡΠ΅ ΡΠΈ. Π’ΠΎΠ²Π° Π΅ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ, Π·Π° Π΄Π° ΠΌΠΎΠΆΠ΅ Π±ΡΠ°ΡΠ·ΡΡΡΡ ΡΠΏΠΎΠΊΠΎΠΉΠ½ΠΎ Π΄Π° ΠΊΠ΅ΡΠΈΡΠ° ΡΠ°ΠΉΠ»Π° Π·Π° Π΄ΡΠ»ΡΠ³ ΠΏΠ΅ΡΠΈΠΎΠ΄. ΠΠΊΠΎ ΡΠ°ΠΉΠ»ΡΡ Π²ΡΠ΅ ΠΏΠ°ΠΊ ΡΠ΅ ΠΏΡΠΎΠΌΠ΅Π½ΠΈ, Ρ Π΅ΡΡΡ ΠΌΡ ΡΡΡΠΎ ΡΠ΅ ΡΠ΅ ΠΏΡΠΎΠΌΠ΅Π½ΠΈ, ΠΊΠΎΠ΅ΡΠΎ ΠΎΡ ΡΠ²ΠΎΡ ΡΡΡΠ°Π½Π° ΡΠ΅ Π½Π°ΠΊΠ°ΡΠ° Π±ΡΠ°ΡΠ·ΡΡΠ° Π΄Π° ΠΈΠ·ΡΠ΅Π³Π»ΠΈ ΡΠ°ΠΉΠ»Π° ΠΎΡΠ½ΠΎΠ²ΠΎ.
ΠΠ° ΡΡΠΆΠ°Π»Π΅Π½ΠΈΠ΅, Π² ΠΌΠΎΡ ΠΌΠ΅ΡΠΎΠ΄, ΠΏΡΠΎΠΌΡΠ½Π°ΡΠ° Π½Π° ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡΡΠ° ΡΡΠ΅Π· ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° ΡΡΠ΅Π΄Π°ΡΠ° Π½Π΅ Π²ΠΎΠ΄ΠΈ Π΄ΠΎ ΠΏΡΠΎΠΌΡΠ½Π° Π½Π° Ρ Π΅Ρ ΡΡΠΎΠΉΠ½ΠΎΡΡΡΠ° Π½Π° ΡΠ°ΠΉΠ»Π°, ΠΊΠΎΠ΅ΡΠΎ ΠΎΠ·Π½Π°ΡΠ°Π²Π°, ΡΠ΅ ΠΊΠ΅ΡΠ° Π½Π° Π±ΡΠ°ΡΠ·ΡΡΠ° ΡΡΡΠ±Π²Π° Π΄Π° Π±ΡΠ΄Π΅ ΠΈΠ½Π²Π°Π»ΠΈΠ΄ΠΈΡΠ°Π½ ΠΏΠΎ Π΄ΡΡΠ³ Π½Π°ΡΠΈΠ½. ΠΠ· Π½ΡΠΌΠ°ΠΌ ΡΠΎΠ·ΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌ, Π·Π°ΡΠΎΡΠΎ ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΡΠ΅ ΡΠ°Π·Π²ΡΡΡΠ°Ρ Π² ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ ΡΡΠ΅Π΄ΠΈ.
Π‘ΡΠ±ΠΈΡΠ°ΠΌΠ΅ ΡΠΈΠ½Π°Π»Π½ΠΈΡ ΠΎΠ±ΡΠ°Π·
ΠΠ°ΠΉ-ΡΠ΅ΡΠ½Π΅.
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;"]Π‘Π΅Π³Π° ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡΡ ΠΎΠ±ΡΠ°Π· ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΡΠ΄Π΅ ΡΡΠ±ΡΠ°Π½ ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½ Π½Π°Π²ΡΡΠΊΡΠ΄Π΅.
ΠΠ·ΡΠΎΡΠ½ΠΈΠΊ: habr.com
