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:
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:
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