Salut tuturor! Aceasta este a doua postare din seria noastră, în care arătăm cum să desfășurăm aplicații web moderne pe Red Hat OpenShift.

În postarea anterioară, am atins ușor posibilitățile noului imagini builder S2I (source-to-image), care este destinat construirii și desfășurării aplicațiilor web moderne pe platforma OpenShift. Atunci ne-a interesat tema desfășurării rapide a aplicației, iar astăzi vom analiza cum să utilizăm imaginea S2I ca un builder 'curat' și să o combinăm cu asamblările asociate din OpenShift.
Imagine builder curată
Așa cum am menționat în prima parte, majoritatea aplicațiilor web moderne au un așa-numit stadiu de construire, în timpul căruia au loc de obicei operații precum transpilararea codului, concatenarea mai multor fișiere și minificarea. Fișierele rezultate de la aceste operații - și anume HTML static, JavaScript și CSS - sunt plasate în dosarul output. Locația acestui dosar depinde de instrumentele de construire utilizate, iar pentru React, acesta va fi dosarul .\/build (vom reveni la această problemă mai jos).
Source-to-Image (S2I)
În această postare nu ne ocupăm deloc de tema 'ce este S2I și cum se folosește' (detalii despre aceasta pot fi găsite ), dar este important să înțelegem clar cele două etape ale acestui proces pentru a înțelege ce face imaginea Web App Builder.
Etapa de asamblare (assemble phase)
Etapa de asamblare este foarte asemănătoare cu ceea ce se întâmplă atunci când rulați docker build și obțineți o nouă imagine Docker. Prin urmare, această etapă are loc atunci când porniți o construcție pe platforma OpenShift.
În cazul imaginii Web App Builder, instalarea dependențelor aplicației tale și inițierea construcției sunt gestionate de . În mod implicit, imaginea builder folosește construcția npm run build, dar aceasta poate fi suprascrisă prin variabila de mediu NPM_BUILD.
Așa cum am menționat anterior, locația aplicației finale, deja compilată, depinde de instrumentele utilizate. De exemplu, în cazul React, aceasta va fi folderul /build, iar pentru aplicațiile Angular – folderul project_name/dist. Și, așa cum a fost arătat în postarea anterioară, locația catalogului output, care este setat implicit ca build, poate fi suprascrisă prin variabila de mediu OUTPUT_DIR. De asemenea, având în vedere că locația folderului output diferă de la un framework la altul, pur și simplu copiați output-ul generat în folderul standard din imagine, și anume în /opt/apt-root/output. Aceasta este importantă pentru înțelegerea părții următoare a acestui articol, dar să trecem rapid la următorul pas – etapa de rulare (run phase).
Etapa de rulare (run phase)
Această etapă apare atunci când se face un apel docker run pentru o nouă imagine, creată în etapa de asamblare. Acest lucru se întâmplă și atunci când se desfășoară implementarea pe platforma OpenShift. În mod implicit folosește pentru a servi conținut static aflat în catalogul output standard menționat mai sus.
Această metodă este bună pentru desfășurarea rapidă a aplicațiilor, dar în general nu este recomandat să serveți conținut static în acest mod. Deoarece în realitate servim doar conținut static, Node.js instalat în imaginea noastră nu este necesar – este suficient un server web.
Cu alte cuvinte, la asamblare avem nevoie de un lucru, iar la execuție – de altul. Într-o astfel de situație, construcțiile înlănțuite (chained builds) devin utile.
Construcții înlănțuite (chained builds)
Iată ce scrie despre în documentația OpenShift:
«Două construcții pot fi legate între ele, una generând o entitate compilată, iar cealaltă plasând această entitate într-o imagine separată, care este utilizată pentru a rula această entitate».
Cu alte cuvinte, putem folosi imaginea Web App Builder pentru a rula construcția noastră, iar apoi putem folosi imaginea serverului web, același NGINX, pentru a servi conținutul nostru.
Astfel, putem aplica imaginea Web App Builder ca un builder „curat” și, în același timp, avem o imagine runtime de dimensiuni reduse.
Acum să analizăm acest lucru printr-un exemplu concret.
Pentru antrenament, vom folosi , creată cu ajutorul instrumentului CLI create-react-app.
Să aducem totul împreună cu ajutorul .
Să detaliem acest fișier și să începem cu secțiunea parametrelor.
parametrii:
- nume: SOURCE_REPOSITORY_URL
descriere: URL-ul sursă pentru aplicație
displayName: URL sursă
necesar: adevărat
- nume: SOURCE_REPOSITORY_REF
descriere: Numele ramurii pentru aplicație
displayName: Ramura sursă
valoare: master
necesar: adevărat
- nume: SOURCE_REPOSITORY_DIR
descriere: Locul din repo-ul sursă al aplicației
displayName: Director sursă
valoare: .
necesar: adevărat
- nume: OUTPUT_DIR
descriere: Locul fișierelor statice compilate din constructorul aplicațiilor tale web
displayName: Director de ieșire
valoare: build
necesar: fals
Aici totul este destul de clar, dar trebuie să acordați atenție parametrului OUTPUT_DIR. Pentru aplicația React din exemplul nostru nu trebuie să vă faceți griji, deoarece React folosește ca director de ieșire valoarea implicită, dar în cazul Angular sau altceva, acest parametru va trebui schimbat corespunzător.
Acum să ne uităm la secțiunea ImageStreams.
- apiVersion: v1
kind: ImageStream
metadata:
name: react-web-app-builder // 1
spec: {}
- apiVersion: v1
kind: ImageStream
metadata:
name: react-web-app-runtime // 2
spec: {}
- apiVersion: v1
kind: ImageStream
metadata:
name: web-app-builder-runtime // 3
spec:
tags:
- name: latest
from:
kind: DockerImage
name: nodeshift/ubi8-s2i-web-app:10.x
- apiVersion: v1
kind: ImageStream
metadata:
name: nginx-image-runtime // 4
spec:
tags:
- name: latest
from:
kind: DockerImage
name: 'centos/nginx-112-centos7:latest'
Uitați-vă la a treia și a patra imagine. Ambele sunt definite ca imagini Docker, iar aici este clar de unde provin.
A treia imagine este web-app-builder, și provine din nodeshift/ubi8-s2i-web-app cu eticheta 10.x pe .
A patra este imaginea NGINX (versiunea 1.12) cu eticheta latest pe .
Acum să ne uităm la primele două imagini. Ambele sunt goale la început și sunt create doar în etapa de construcție (build phase). Prima imagine - react-web-app-builder - va fi rezultatul etapei de asamblare, care va combina imaginea web-app-builder-runtime și codul nostru sursă. De aceea am inclus în numele acestei imagini „-builder”.
A doua imagine - react-web-app-runtime - va fi rezultatul combinării nginx-image-runtime și a unor fișiere din imaginea react-web-app-builder. Această imagine va fi folosită și la desfășurare și va conține doar serverul web și HTML, JavaScript, CSS statice ale aplicației noastre.
Confuz? Acum să ne uităm la configurațiile de construcție și va fi puțin mai clar.
În șablonul nostru există două configurații de construcție. Iată prima dintre ele, și este destul de standardă:
apiVersion: v1
kind: BuildConfig
metadata:
name: react-web-app-builder
spec:
output:
to:
kind: ImageStreamTag
name: react-web-app-builder:latest // 1
source: // 2
git:
uri: ${SOURCE_REPOSITORY_URL}
ref: ${SOURCE_REPOSITORY_REF}
contextDir: ${SOURCE_REPOSITORY_DIR}
type: Git
strategy:
sourceStrategy:
env:
- name: OUTPUT_DIR // 3
value: ${OUTPUT_DIR}
from:
kind: ImageStreamTag
name: web-app-builder-runtime:latest // 4
incremental: true // 5
type: Source
triggers: // 6
- github:
secret: ${GITHUB_WEBHOOK_SECRET}
type: GitHub
- type: ConfigChange
- imageChange: {}
type: ImageChange
Așa cum vedem, linia cu eticheta 1 spune că rezultatul acestei construcții va fi plasat în imaginea react-web-app-builder, pe care am văzut-o mai devreme în secțiunea ImageStream.
Linia cu eticheta 2 spune de unde se va lua codul. În cazul nostru, acesta este un repository git, iar locația, ref și folderul de context sunt definite prin parametrii pe care i-am văzut mai sus.
Linia cu eticheta 3 – aceasta a fost deja menționată în secțiunea parameter. Ea adaugă o variabilă de mediu OUTPUT_DIR, care în exemplul nostru este egală cu build.
Linia cu eticheta 4 spune să folosească imaginea web-app-builder-runtime, pe care am văzut-o deja în secțiunea ImageStream.
Linia cu eticheta 5 spune că dorim să folosim o construcție incrementală, dacă imaginea S2I o suportă, iar imaginea Web App Builder – o suportă. La prima rulare, după finalizarea etapei de asamblare, imaginea va salva folderul node_modules într-un fișier arhivat. Apoi, la rulările ulterioare, imaginea va decomprima pur și simplu acest folder pentru a reduce durata construcției.
Și, în final, linia cu eticheta 6 – sunt doar câțiva triggeri pentru a lansa construcția automat, fără intervenție manuală, atunci când ceva se schimbă.
În general, aceasta este o configurație standard de construit.
Acum să ne uităm la a doua configurație de construire. Este foarte asemănătoare cu prima, dar există o diferență importantă.
apiVersion: v1
kind: BuildConfig
metadata:
name: react-web-app-runtime
spec:
output:
to:
kind: ImageStreamTag
name: react-web-app-runtime:latest // 1
source: // 2
type: Image
images:
- from:
kind: ImageStreamTag
name: react-web-app-builder:latest // 3
paths:
- sourcePath: /opt/app-root/output/. // 4
destinationDir: . // 5
strategy: // 6
sourceStrategy:
from:
kind: ImageStreamTag
name: nginx-image-runtime:latest
incremental: true
type: Source
triggers:
- github:
secret: ${GITHUB_WEBHOOK_SECRET}
type: GitHub
- type: ConfigChange
- type: ImageChange
imageChange: {}
- type: ImageChange
imageChange:
from:
kind: ImageStreamTag
name: react-web-app-builder:latest // 7
Deci, a doua configurație a compilării este react-web-app-runtime, și începe relativ standard.
Linia cu eticheta 1 nu conține nimic nou – doar indică faptul că rezultatul compilării este plasat în imaginea react-web-app-runtime.
Linia cu eticheta 2, ca în configurația anterioară, indică de unde să luăm codul sursă. Dar observați că aici spunem că acesta este preluat dintr-o imagine. Și anume, din imaginea pe care tocmai am creat-o – din react-web-app-builder (specificată în linia cu eticheta 3). Fișierele pe care dorim să le folosim se află în interiorul imaginii și locația lor acolo este specificată în linia cu eticheta 4, în cazul nostru este /opt/app-root/output/. Dacă vă amintiți, exact acolo sunt plasate fișierele generate ca rezultat al compilării aplicației noastre.
Directorul de destinație, specificat în termenul cu eticheta 5, este pur și simplu directorul curent (toate acestea, amintim, se desfășoară în interiorul unei chestii magice numită OpenShift, nu pe computerul dumneavoastră local).
Secțiunea strategy – linia cu eticheta 6 – este, de asemenea, similară cu prima configurație a compilării. Numai că de această dată intenționăm să folosim nginx-image-runtime, pe care l-am văzut deja în secțiunea ImageStream.
În final, linia cu eticheta 7 – este secțiunea de declanșatoare, care activează această compilare de fiecare dată când se schimbă imaginea react-web-app-builder.
În rest, acest șablon conține o configurație standard de desfășurare, precum și lucruri legate de servicii și rute, dar nu ne vom aprofunda în acestea. Observați că imaginea care va fi desfășurată este imaginea react-web-app-runtime.
Desfășurarea aplicației
Deci, după ce am aruncat o privire asupra șablonului, să vedem cum să-l folosim pentru desfășurarea aplicației.
Putem folosi instrumentul client OpenShift numit oc pentru a desfășura șablonul nostru:
$ find . | grep openshiftio | grep application | xargs -n 1 oc apply -f
$ oc new-app --template react-web-app -p SOURCE_REPOSITORY_URL=https://github.com/lholmquist/react-web-app
Prima comandă din ecranul de mai sus – este o modalitate intenționat ingineriască de a găsi șablonul /openshiftio/application.yaml.
A doua comandă pur și simplu creează o nouă aplicație pe baza acestui șablon.
După ce aceste comenzi se execută, vom vedea că avem două compilări:

Iar întorcându-ne pe ecranul Overview, vom vedea pod-ul care a fost lansat:

Un clic pe link – și vom ajunge la aplicația noastră, care reprezintă pagina aplicației React App implicit:

Anexa 1
Pentru iubitorii de Angular, avem și noi .
Șablonul este similar, cu excepția variabilei OUTPUT_DIR.
Completarile 2
În acest articol, am folosit ca server web NGINX, dar este destul de ușor să-l înlocuim cu Apache, pur și simplu schimbând în fișierul șablon. pe .
Concluzie
În prima parte a acestei serii, am arătat cum să implementați rapid aplicații web moderne pe platforma OpenShift. Astăzi, vom analiza ce face imaginea Web App și cum se poate combina cu un server web curat de tip NGINX prin intermediul construirilor înlanțuite (chained build) pentru a organiza o construcție mai adecvată pentru condițiile de producție. În următorul, articol concluziv al acestei serii, vă vom arăta cum să rulați pe OpenShift un server de dezvoltare pentru aplicația dvs. și să asigurați sincronizarea fișierelor locale și de la distanță.
Cuprinsul acestei serii de articole
- Partea 1: ;
- Partea 2: cum să aplicați o nouă imagine S2I împreună cu o imagine existentă de server HTTP, de exemplu, NGINX, folosind construcții înlanțuite OpenShift pentru a organiza implementarea în producție;
- Partea 3: cum să rulați pe platforma OpenShift un server de dezvoltare pentru aplicația dvs. și să-l sincronizați cu sistemul local de fișiere.
Resurse suplimentare
- Carte electronică gratuită .
- Informații despre .
Sursa: habr.com
