Setšoantšo sa Docker bakeng sa ho ajoa ha Kopo e le 'ngoe ea Leqephe

Sesebelisoa sa leqephe le le leng (SPA) ke sete sa lifaele tsa JavaScript le HTML tse sa fetoheng, hammoho le litšoantšo le lisebelisoa tse ling. Hobane ha li fetohe ka matla, ho li phatlalatsa inthaneteng ho bonolo haholo. Ho na le palo e kholo ea litšebeletso tse theko e tlaase le tse sa lefelloeng bakeng sa sena, ho qala ka GitHub Pages e bonolo (le bakeng sa ba bang esita le ka narod.ru) le ho qetella ka CDN joaloka Amazon S3. Leha ho le joalo, ke ne ke hloka ntho e ’ngoe hape.

Ke ne ke hloka setšoantšo sa Docker se nang le SPA e le hore se ka qalisoa habonolo ka bobeli tlhahisong e le karolo ea sehlopha sa Kubernetes, le mochining oa moqapi oa morao-rao ea sa tsebeng hore na SPA ke eng.

Ke iketsetse litlhokahalo tse latelang tsa setšoantšo bakeng sa ka:

  • boiketlo ba tšebeliso (empa eseng kopano);
  • boholo bo fokolang ka bobeli ho ea ka disk le RAM;
  • tlhophiso ka mefuta-futa ea tikoloho e le hore setšoantšo se ka sebelisoa libakeng tse fapaneng;
  • kabo e atlehileng ka ho fetisisa ea lifaele.

Kajeno ke tla u bolella kamoo:

  • mala nginx;
  • haha ​​brotli ho tsoa mehloling;
  • ruta lifaele tse tsitsitseng ho utloisisa mefuta-futa ea tikoloho;
  • mme ehlile u ka kopanya setšoantšo sa Docker ho tsoa ho tsena tsohle.

Sepheo sa sengoloa sena ke ho arolelana boiphihlelo ba ka le ho hlohlelletsa litho tsa sechaba tse nang le boiphihlelo ho nyatsuoa ka mokhoa o hahang.

Ho haha ​​setšoantšo bakeng sa kopano

Ho etsa hore setšoantšo sa ho qetela sa Docker se senyenyane ka boholo, o hloka ho khomarela melao e 'meli: bonyane ba lihlopha le setšoantšo sa motheo sa minimalistic. E 'ngoe ea litšoantšo tse nyane ka ho fetisisa ke setšoantšo sa Alpine Linux, kahoo ke sona seo ke tla se khetha. Ba bang ba ka 'na ba pheha khang ea hore Alpine ha e tšoanelehe bakeng sa tlhahiso, 'me e ka' na eaba ba nepile. Empa ka bonna, ha ho mohla nkileng ka ba le mathata leha e le afe le eena ebile ha ho na likhang khahlanong le eena.

Ho ba le mekhahlelo e fokolang, ke tla kopanya setšoantšo ka mekhahlelo e 2. Ea pele ke moralo; lisebelisoa tsohle tse thusang le lifaele tsa nakoana li tla sala ho eona. 'Me karolong ea ho qetela ke tla ngola feela phetolelo ea ho qetela ea kopo.

Ha re qaleng ka setšoantšo se thusang.

Bakeng sa ho bokella kopo ea SPA, hangata o hloka node.js. Ke tla nka setšoantšo sa semmuso, se tlang le batsamaisi ba liphutheloana tsa npm le khoele. Lebitsong la ka, ke tla eketsa node-gyp, e hlokahalang ho aha liphutheloana tsa npm, le compressor ea Brotli e tsoang ho Google, e tla ba molemo ho rona hamorao.

Dockerfile e nang le maikutlo.

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

Hona joale ke ntse ke loanela minimalism, kahoo setšoantšo se kopantsoe ke sehlopha se le seng se seholo.

Setšoantšo se phethiloeng se ka fumanoa mona: https://hub.docker.com/r/alexxxnf/spa-builder. Le hoja ke khothaletsa ho se itšetlehe ka litšoantšo tsa batho ba bang le ho bokella ea hau.

nginx

U ka sebelisa seva efe kapa efe ea marang-rang ho aba litaba tse sa fetoheng. Ke tloaetse ho sebetsa ka nginx, kahoo ke tla e sebelisa hona joale.

Nginx e na le setšoantšo sa semmuso sa Docker, empa e na le li-module tse ngata haholo bakeng sa kabo e bonolo ea static. Ke life tse kenyelletsoeng ho fana ka tsona li ka bonoa ke sehlopha se khethehileng kapa ho Dockerfile ea molao.

$ docker matha --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

Ke tla sebelisa Dockerfile e le motheo, empa ke tla siea ho eona feela se hlokahalang ho aba litaba tse tsitsitseng. Mofuta oa ka o ke ke oa khona ho sebetsa holim'a HTTPS, e ke ke ea tšehetsa tumello, le tse ling tse ngata. Empa mofuta oa ka o tla khona ho tsamaisa lifaele tse hatelitsoeng ka algorithm ea Brotli, e sebetsang hantle hanyane ho feta gzip. Re tla hatella lifaele hang; ha ho hlokahale ho etsa sena hang-hang.

Ena ke Dockerfile eo ke qetetseng ka eona. Maikutlo ka Serussia ke a ka, ka Senyesemane - ho tloha qalong.

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;"]

Hang-hang ke tla lokisa nginx.conf hore gzip le brotli li khonehe ka ho sa feleng. Ke tla kenyelletsa lihlooho tsa caching, hobane re ke ke ra hlola re fetola static. 'Me taba ea ho qetela e tla ba ho tsamaisa likopo tsohle tse 404 ho index.html, sena sea hlokahala bakeng sa ho tsamaea ho 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";
            }
        }
    }
}

U ka khoasolla setšoantšo se phethiloeng mona: https://hub.docker.com/r/alexxxnf/nginx-spa. E nka 10,5 MB. Nginx ea mantlha e nkile 19,7 MB. Thahasello ea ka ea lipapali e khotsofetse.

Ho ruta li-statics ho utloisisa maemo a fapaneng a tikoloho

Hobaneng ho ka hlokahala litlhophiso ho SPA? Mohlala, molemong oa ho hlakisa hore na u ka sebelisa RESTful API efe. Ka tloaelo, litlhophiso tsa tikoloho e lakatsehang li fetisetsoa ho SPA sethaleng sa kaho. Haeba u hloka ho fetola ntho e itseng, u tla tlameha ho tsosolosa kopo. ha ke e batle. Ke batla hore kopo e hahoe hang sethaleng sa CI, 'me e lokisoe ka hohle kamoo ho hlokahalang sethaleng sa CD ho sebelisa mefuta-futa ea tikoloho.

Ehlile, lifaele tsa static ka botsona ha li utloisise mefuta efe kapa efe ea tikoloho. Ka hona, o tla tlameha ho sebelisa leqheka. Setšoantšong sa ho qetela, nke ke ka qala nginx, empa script e khethehileng ea khetla e tla bala mefuta-futa ea tikoloho, e ngolle lifaele tse tsitsitseng, e li hatelle, ebe feela e fetisetsa taolo ho nginx.

Bakeng sa morero ona, Dockerfile e fana ka paramente ea ENTRYPOINT. Ha re mo fe lengolo le latelang (re sebelisa mohlala oa 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-файлах
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 "$@"

E le hore script e etse mosebetsi oa eona, litlhophiso li tlameha ho ngoloa lifaeleng tsa js ka foromo ena: ${API_URL}.

Ho bohlokoa ho hlokomela hore li-SPA tse ngata tsa sejoale-joale li eketsa li-hashes lifaeleng tsa tsona ha li haha. Sena sea hlokahala e le hore sebatli se ka boloka faele ka mokhoa o sireletsehileng nako e telele. Haeba faele e fetoha, hash ea eona e tla fetoha, e leng se tla qobella sebapali ho khoasolla faele hape.

Ka bomalimabe, ka mokhoa oa ka, ho fetola tlhophiso ka mefuta e fapaneng ea tikoloho ha ho lebise phetohong ea hash ea faele, ho bolelang hore cache ea sebatli e tlameha ho se sebetse ka tsela e 'ngoe. Ha ke na bothata bona hobane litlhophiso tse fapaneng li sebelisoa libakeng tse fapaneng.

Ho kopanya setšoantšo sa ho qetela

Qetellong.

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;"]

Hona joale setšoantšo se hlahisoang se ka bokelloa 'me sa sebelisoa kae kapa kae.

Source: www.habr.com