Umfanekiso weDocker wokusasazwa kweSicelo sePhepha elinye

I-Single-page Application (SPA) yiseti yeJavaScript engatshintshiyo kunye neefayile zeHTML, kunye nemifanekiso kunye nezinye izixhobo. Ngenxa yokuba azitshintshi ngokuguqukayo, ukuzipapasha kwi-intanethi kulula kakhulu. Kukho inani elikhulu leenkonzo ezingabizi kwaye zisimahla kule nto, ukuqala ngamaPhepha e-GitHub alula (kunye nakwabanye kunye ne-narod.ru) kwaye iphele nge-CDN efana ne-Amazon S3. Noko ke, ndandifuna enye into.

Bendifuna umfanekiso weDocker one-SPA ukuze ube nokusungulwa ngokulula zombini kwimveliso njengenxalenye yeqela le-Kubernetes, nakumatshini womphuhlisi osemva ongayaziyo ukuba yintoni i-SPA.

Ndizimisele ezi mfuno zilandelayo zomfanekiso:

  • ukusetyenziswa lula (kodwa hayi indibano);
  • ubuncinci besayizi zombini ngokwe diski kunye ne-RAM;
  • uqwalaselo ngokusebenzisa izinto eziguquguqukayo zemo engqongileyo ukuze umfanekiso usetyenziswe kwiindawo ezahlukeneyo;
  • unikezelo olusebenzayo lweefayile.

Namhlanje ndiza kukuxelela indlela:

  • ithumbu nginx;
  • ukwakha brotli ukusuka kwimithombo;
  • fundisa iifayile ezingashukumiyo ukuqonda izinto ezahlukeneyo zokusingqongileyo;
  • kwaye ngokuqinisekileyo ungahlanganisa njani umfanekiso weDocker kuyo yonke le nto.

Injongo yeli nqaku kukwabelana ngamava am kwaye ndixhokonxe amalungu oluntu anamava ukuba agxeke ngendlela eyakhayo.

Ukwakha umfanekiso wendibano

Ukwenza umfanekiso weDocker wokugqibela ube mncinci ngobukhulu, kufuneka unamathele kwimithetho emibini: ubuncinci bemigangatho kunye nomfanekiso wesiseko esincinci. Omnye weyona mifanekiso mincinci isiseko ngumfanekiso weAlpine Linux, ke yile nto ndiza kuyikhetha. Abanye banokuthi iAlpine ayifanelekanga ukuveliswa, kwaye banokuthi balungile. Kodwa mna ngokwam andizange ndanengxaki naye kwaye akukho zingxabano ezichasene naye.

Ukuba nemigangatho embalwa, ndiza kudibanisa umfanekiso kwizigaba ezi-2. Eyokuqala yidrafti; zonke izinto ezincedisayo kunye neefayile zexeshana ziya kuhlala kuyo. Kwaye kwinqanaba lokugqibela ndiya kubhala kuphela inguqu yokugqibela yesicelo.

Masiqale ngomfanekiso oncedisayo.

Ukuze uqokelele isicelo se-SPA, udla ngokufuna i-node.js. Ndiza kuthatha umfanekiso osemthethweni, oza kunye ne-npm kunye nabaphathi bephakheji yentambo. Egameni lam, ndiza kongeza i-node-gyp, efunekayo ukwakha iiphakheji ze-npm, kunye ne-Brotli compressor evela kuGoogle, eya kuba luncedo kuthi kamva.

Dockerfile ngezimvo.

# Π‘Π°Π·ΠΎΠ²Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π·
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

Sele ndilapha ndilwela ubuncinci, ngoko umfanekiso uhlanganiswe liqela elinye elikhulu.

Umfanekiso ogqityiweyo unokufunyanwa apha: https://hub.docker.com/r/alexxxnf/spa-builder. Nangona ndincoma ukuba ungathembeli kwimifanekiso yabanye abantu kwaye uqokelele eyakho.

nginx

Ungasebenzisa nayiphi na iseva yewebhu ukusabalalisa umxholo omileyo. Ndiqhele ukusebenza nge nginx, so ndizoyisebenzisa ngoku.

I-Nginx inomfanekiso we-Docker esemthethweni, kodwa ineemodyuli ezininzi kakhulu zokusasazwa kwe-static. Ziziphi ezibandakanyiweyo ekuhanjisweni zingabonwa liqela elikhethekileyo okanye kwiDockerfile esemthethweni.

$ 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

Ndiza kusebenzisa i-Dockerfile njengesiseko, kodwa ndiya kushiya kuyo kuphela into efunekayo ukusabalalisa umxholo omileyo. Inguqulelo yam ayizukwazi ukusebenza nge-HTTPS, ayizukuxhasa ugunyaziso, nokunye okuninzi. Kodwa inguqulelo yam iya kuba nakho ukusasaza iifayile ezicinezelwe nge-algorithm yeBrotli, esebenza kancinci kunegzip. Siza kucinezela iifayile kube kanye; akukho mfuneko yakwenza oku kubhabho.

Le yiDockerfile endigqibe ngayo. Izimvo ngesiRashiya zezam, ngesiNgesi - ukusuka ekuqaleni.

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

Ndizakulungisa ngoko nangoko nginx.conf ukuze i-gzip kunye ne-brotli zisebenze ngokungagqibekanga. Ndiza kubandakanya i-caching headers, kuba asisoze sitshintshe i-static. Kwaye uchuku lokugqibela luya kuba kukwalathisa zonke izicelo ezingama-404 kwi-index.html, oku kuyimfuneko kwi-navigation kwi-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";
            }
        }
    }
}

Ungakhuphela umfanekiso ogqityiweyo apha: https://hub.docker.com/r/alexxxnf/nginx-spa. Ithatha i-10,5 MB. I-nginx yoqobo ithathe i-19,7 MB. Umdla wam wezemidlalo wanelisiwe.

Ukufundisa i-statics ukuqonda izinto eziguquguqukayo zokusingqongileyo

Kutheni iisetingi zinokufuneka kwi-SPA? Umzekelo, ukuze uchaze ukuba yeyiphi i-RESTful API emayisetyenziswe. Ngokuqhelekileyo, iisetingi zendawo efunekayo zikhutshelwa kwi-SPA kwinqanaba lokwakha. Ukuba ufuna ukutshintsha into ethile, kuya kufuneka uphinde uyakhe isicelo. andiyifuni. Ndifuna isicelo sakhiwe kube kanye kwinqanaba leCI, kwaye iqwalaselwe kangangoko kuyimfuneko kwinqanaba le-CD usebenzisa izinto eziguquguqukayo zokusingqongileyo.

Ewe kunjalo, iifayile ezimileyo ngokwazo aziqondi naziphi na izinto eziguquguqukayo zokusingqongileyo. Ngoko ke, kuya kufuneka usebenzise iqhinga. Kumfanekiso wokugqibela, andiyi kusungula i-nginx, kodwa iskripthi esikhethekileyo seqokobhe esiya kufunda izinto eziguquguqukayo zendalo, zibhale kwiifayile ezimileyo, zizicinezele, kwaye emva koko udlulisele ulawulo kwi-nginx.

Ngale njongo, iDockerfile ibonelela nge-ENTRYPOINT iparamitha. Masimnike esi script silandelayo (sisebenzisa i-Angular njengomzekelo):

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

Ukuze iskripthi senze umsebenzi waso, useto kufuneka lubhalwe kwiifayile zejs kule fomu: ${API_URL}.

Kuyaphawuleka ukuba uninzi lwee-SPA zanamhlanje zongeza i-hashes kwiifayile zazo xa zisakha. Oku kuyimfuneko ukwenzela ukuba isikhangeli singakwazi ukugcina ifayile ngokukhuselekileyo ixesha elide. Ukuba ifayile iyatshintsha, ke i-hash yayo iya kutshintsha, leyo iya kunyanzela umkhangeli ukuba akhuphe ifayile kwakhona.

Ngelishwa, kwindlela yam, ukutshintsha uqwalaselo ngokusebenzisa izinto eziguquguqukayo zemo engqongileyo akukhokeleli kutshintsho kwihashi yefayile, okuthetha ukuba i-cache yesikhangeli kufuneka ingasebenzi ngenye indlela. Andinayo le ngxaki kuba ulungelelwaniso olwahlukileyo lubekwe kwindawo ezahlukeneyo.

Ukudibanisa umfanekiso wokugqibela

Ekugqibeleni.

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

Ngoku umfanekiso obangelwayo unokudityaniswa kwaye usetyenziswe naphi na.

umthombo: www.habr.com