ΠΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ° ΡΠΎ Π΅Π΄Π½Π° ΡΡΡΠ°Π½ΠΈΡΠ° (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
ΠΠ΅ΡΠ΅ ΠΎΠ²Π΄Π΅ ΡΠ΅ Π±ΠΎΡΠ°ΠΌ Π·Π° ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΠΈΠ·Π°ΠΌ, ΠΏΠ° ΡΠ»ΠΈΠΊΠ°ΡΠ° ΡΠ° ΡΠΎΡΡΠ°Π²ΡΠ²Π° Π΅Π΄Π΅Π½ Π³ΠΎΠ»Π΅ΠΌ ΡΠΈΠΌ.
ΠΠΎΡΠΎΠ²Π°ΡΠ° ΡΠ»ΠΈΠΊΠ° ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΡΠ° Π½Π°ΡΠ΄Π΅ΡΠ΅ ΠΎΠ²Π΄Π΅:
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";
}
}
}
}
ΠΠΎΡΠΎΠ²Π°ΡΠ° ΡΠ»ΠΈΠΊΠ° ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΡΠ° ΠΏΡΠ΅Π·Π΅ΠΌΠ΅ΡΠ΅ ΠΎΠ²Π΄Π΅:
ΠΠ°ΡΡΠ°Π²Π° Π·Π° ΡΡΠ°ΡΠΈΠΊΠ° Π·Π° ΡΠ°Π·Π±ΠΈΡΠ°ΡΠ΅ Π½Π° ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈΡΠ΅ Π½Π° ΠΎΠΊΠΎΠ»ΠΈΠ½Π°ΡΠ°
ΠΠΎΡΡΠΎ ΠΌΠΎΠΆΠ΅Π±ΠΈ ΡΠ΅ ΠΏΠΎΡΡΠ΅Π±Π½ΠΈ ΠΏΠΎΡΡΠ°Π²ΠΊΠΈ Π²ΠΎ 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