Ata Docker mo le tufatufaina o Talosaga Itulau Tasi

Talosaga tasi itulau (SPA) o se seti o faila JavaScript ma HTML faila, faʻapea foʻi ma ata ma isi punaoa. Ona latou te le suia malosi, lolomiina i luga ole laiga e matua faigofie lava. O loʻo i ai se numera tele o auaunaga taugofie ma e leai se totogi mo lenei mea, e amata ile GitHub Pages faigofie (ma mo nisi e oʻo lava ile narod.ru) ma faʻaiʻu ile CDN pei ole Amazon S3. Ae peitai, sa ou manaomia se isi mea.

Na ou manaʻomia se ata Docker ma le SPA ina ia faigofie ona faʻalauiloa uma i le gaosiga o se vaega o le Kubernetes cluster, ma luga o le masini a se tagata faʻapipiʻi pito i tua e le iloa po o le a le SPA.

Ua ou fuafuaina mea nei e manaʻomia mo aʻu lava:

  • faigofie o le faʻaaogaina (ae le o le faʻapotopotoga);
  • laʻititi laʻititi i tulaga ole disk ma le RAM;
  • faʻatulagaina e ala i fesuiaiga o le siosiomaga ina ia mafai ona faʻaogaina le ata i siosiomaga eseese;
  • le tufatufaina sili ona lelei o faila.

O le asō o le a ou taʻu atu ia te oe pe faapefea:

  • gutu nginx;
  • fausia brotli mai punaoa;
  • a'oa'o faila tu'usa'o e malamalama ai i suiga ole si'osi'omaga;
  • ma ioe pe faʻapefea ona faʻapipiʻi se ata Docker mai nei mea uma.

O le faʻamoemoe o lenei tusiga o le faʻasoa atu lea o loʻu poto masani ma faʻaosofia tagata faʻapitoa i le alalafaga i faitioga aoga.

Fausia se ata mo le faʻapotopotoga

Ina ia faia le ata mulimuli Docker laʻititi i le lapopoa, e tatau ona e tausisi i tulafono e lua: laʻititi laʻititi ma se ata faʻavae laʻititi. O se tasi o ata pito sili ona laiti o le ata Alpine Linux, o le mea lena o le a ou filifilia. Atonu e finau nisi e le talafeagai le Alpine mo le gaosiga, ma atonu e sa'o. Ae ia te a’u lava ia, ou te le’i i ai lava ni faafitauli ia te ia ma e leai foi ni finauga faasaga ia te ia.

Ina ia itiiti ni laulau, o le a ou faʻapipiʻiina le ata i laʻasaga 2. Muamua o se ata faataitai; o mea aoga uma fesoasoani ma faila le tumau o le a tumau i totonu. Ma i le tulaga mulimuli o le a ou tusia i lalo le lomiga mulimuli o le talosaga.

Tatou amata i le ata fesoasoani.

Ina ia mafai ona tuufaatasia se talosaga SPA, e masani ona e manaʻomia node.js. O le a ou ave le ata aloaia, lea e sau foi ma le npm ma le yarn package managers. I luga o aʻu lava sui, o le a ou faʻaopoopoina le node-gyp, lea e manaʻomia e fausia ai ni pusa npm, ma le Brotli compressor mai Google, lea o le a aoga ia i tatou mulimuli ane.

Dockerfile ma faʻamatalaga.

# Базовый образ
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

Ua i ai iinei o lea ou te tau mo le minimalism, o lea ua tuufaatasia ai le ata e le au tele e tasi.

O le ata ua mae'a e mafai ona maua iinei: https://hub.docker.com/r/alexxxnf/spa-builder. E ui lava ou te fautuaina e aua le faʻalagolago i ata a isi tagata ma aoina oe lava.

nginx

E mafai ona e fa'aogaina so'o se 'upega tafa'ilagi e fa'asoa ai mea fa'apitoa. Ua ou masani e galue ma nginx, o lea o le a ou faʻaaogaina nei.

Nginx o loʻo i ai se ata Docker aloaia, ae e tele naua modules mo faʻasalalauga faigofie faigofie. O fea o loʻo aofia i le tuʻuina atu e mafai ona vaʻaia e se 'au faʻapitoa poʻo le Dockerfile aloaia.

$ 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

O le a ou faʻaaogaina le Dockerfile e fai ma faʻavae, ae o le a ou tuʻuina i totonu naʻo mea e manaʻomia e tufatufa atu ai mea faʻapitoa. O laʻu faʻamatalaga o le a le mafai ona galue i luga o HTTPS, o le a le lagolagoina le faʻatagaina, ma sili atu. Ae o laʻu faʻamatalaga o le a mafai ona tufatufaina atu faila faʻapipiʻiina i le Brotli algorithm, lea e sili atu le lelei nai lo le gzip. O le a matou faʻapipiʻi faila i le taimi e tasi; e leai se manaʻoga e faia i luga o le lele.

O le Dockerfile lea na ou faʻamutaina. O faʻamatalaga i le gagana Rusia e aʻu, i le Igilisi - mai le uluai kopi.

faila faila

# Базовый образ снова 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;"]

O le a vave ona ou toe faaleleia nginx.conf ina ia mafai ai ona mafai le gzip ma le brotli ona o le faaletonu. O le a ou aofia ai foʻi ulutala faʻapipiʻi, aua o le a tatou le suia lava. Ma o le pa'i mulimuli o le a toe fa'afo'i uma talosaga e 404 i le index.html, e mana'omia lea mo le folauga i le 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";
            }
        }
    }
}

E mafai ona e sii maia le ata ua mae'a iinei: https://hub.docker.com/r/alexxxnf/nginx-spa. E manaʻomia le 10,5 MB. O le uluai nginx na maua le 19,7 MB. Ua faamalieina lo'u fiafia i taaloga.

Fa'aa'oa'oina fa'amaumauga e malamalama ai i fesuiaiga o le si'osi'omaga

Aisea e ono mana'omia ai fa'atulagaga ile SPA? Mo se fa'ata'ita'iga, ina ia fa'ailoa mai po'o fea le API RESTful e fa'aoga. E masani lava, o fa'atulagaga mo le si'osi'omaga e mana'omia e tu'u atu ile SPA ile taimi faufale. Afai e te manaʻomia le suia o se mea, e tatau ona e toe fausia le talosaga. Ou te le manao i ai. Ou te manaʻo ia fausia le talosaga i le taimi e tasi i le tulaga CI, ma faʻapipiʻi i le tele e manaʻomia ai i le CD stage e faʻaaoga ai fesuiaiga o le siosiomaga.

O le mea moni, o faila static lava latou e le malamalama i soʻo se fesuiaiga o le siosiomaga. O le mea lea, e tatau ona e faʻaaogaina se togafiti. I le ata mulimuli, o le a ou le faʻalauiloaina le nginx, ae o se atigi atigi faʻapitoa e faitau ai suiga o le siosiomaga, tusi i latou i faila faila, faʻapipiʻi, ona faʻafeiloaʻi lea o le pule i le nginx.

Mo lenei faʻamoemoe, o le Dockerfile e tuʻuina atu le ENTRYPOINT parameter. Sei o tatou tuʻuina atu ia te ia le faʻamatalaga o loʻo i lalo (faʻaaogaina Angular e fai ma faʻataʻitaʻiga):

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 "$@"

Ina ia mafai e le tusitusiga ona fai lana galuega, e tatau ona tusia ia faatulagaga i faila js i lenei fomu: ${API_URL}.

E taua le maitauina o le tele o SPA faʻaonaponei e faʻaopoopoina faʻamau i latou faila pe a fau. E manaʻomia lenei mea ina ia mafai e le browser ona faʻapipiʻi saogalemu le faila mo se taimi umi. Afai e suia le faila, ona suia lea o lona hash, lea o le a faamalosia ai le browser e toe sii mai le faila.

O le mea e leaga ai, i laʻu metotia, o le suia o le faʻatulagaina e ala i fesuiaiga o le siosiomaga e le oʻo atu ai i se suiga i le faila hash, o lona uiga e tatau ona faʻaleaogaina le cache browser i se isi auala. E leai so'u fa'afitauli ona o fa'atonuga eseese o lo'o fa'apipi'iina i si'osi'omaga eseese.

Tuu faatasi le ata mulimuli

Mulimuli ane.

faila faila

# Первый базовый образ для сборки
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;"]

O le taimi nei o le ata e maua mai e mafai ona faʻapipiʻiina ma faʻaoga i soʻo se mea.

puna: www.habr.com