Hallo allemaal! Dit is de tweede post in onze serie waarin we laten zien hoe je moderne webapplicaties op Red Hat OpenShift kunt implementeren.

In de vorige post hebben we kort de mogelijkheden van de nieuwe S2I (source-to-image) builder-afbeelding aangeraakt, die bedoeld is voor het bouwen en implementeren van moderne webapplicaties op het OpenShift-platform. Toen lag de focus op het snel implementeren van een applicatie, en vandaag bekijken we hoe we een S2I-afbeelding kunnen gebruiken als een 'schone' builder-afbeelding en deze kunnen combineren met gerelateerde builds op OpenShift.
Schone builder-afbeelding
Zoals we in het eerste deel hebben vermeld, hebben de meeste moderne webapplicaties een zogenaamde bouwfase, waarin meestal operaties zoals code-transpilatie, het samenvoegen van meerdere bestanden en minificatie plaatsvinden. De bestanden die uit deze operaties voortkomen – dat zijn statische HTML, JavaScript en CSS – worden in de output-map opgeslagen. De locatie van deze map hangt meestal af van de gebruikte build-tools, en voor React is dit de map .\/build (hierover komen we later meer terug).
Source-to-Image (S2I)
In deze post behandelen we helemaal niet het onderwerp 'wat is S2I en hoe gebruik je het' (hierover kun je meer lezen ), maar het is belangrijk om een goed begrip te hebben van de twee fasen van dit proces, om te begrijpen wat de Web App Builder-afbeelding doet.
Assemblagefase
De assemblagefase lijkt in wezen sterk op wat er gebeurt wanneer je docker build uitvoert en uiteindelijk een nieuwe Docker-afbeelding ontvangt. Deze fase treedt op wanneer je een build op het OpenShift-platform start.
In het geval van de Web App Builder-afbeelding is het . standaard gebruikt de builder-afbeelding de constructie npm run build, maar deze kan worden overschreven via de omgevingsvariabele NPM_BUILD.
Zoals eerder vermeld, hangt de locatie van de kant-en-klare, samengevoegde applicatie af van welke tools worden gebruikt. In het geval van React bevindt dit zich in de map ./build, en voor Angular-applicaties is dat de map project_name/dist. En zoals in de vorige post al werd aangetoond, kan de locatie van de output-map, die standaard is ingesteld als build, worden overschreven via de omgevingsvariabele OUTPUT_DIR. Aangezien de locatie van de output-map verschilt van framework tot framework, hoeft u alleen de gegenereerde output te kopiëren naar de standaardmap in de afbeelding, namelijk naar /opt/apt-root/output. Dit is belangrijk voor het begrijpen van het vervolg van dit artikel, maar laten we nu snel de volgende fase bekijken – de uitvoeringsfase (run phase).
Uitvoeringsfase (run phase)
Deze fase komt in beeld wanneer voor een nieuwe afbeelding, die is gemaakt tijdens de assemblagefase, een docker run-oproep wordt gedaan. Dit gebeurt ook bij het implementeren op het OpenShift-platform. Standaard gebruikt voor het serveren van statische inhoud, die in de hierboven genoemde standaard output-map ligt.
Deze methode is goed voor een snelle implementatie van applicaties, maar in feite is het niet aan te raden om statische inhoud op deze manier te serveren. Aangezien we daadwerkelijk alleen statische inhoud serveren, is de geïnstalleerde Node.js binnen onze afbeelding niet nodig – een webserver is voldoende.
Met andere woorden, tijdens de assemblage hebben we één ding nodig, tijdens de uitvoering iets anders. In zo'n situatie zijn gekoppelde builds (chained builds) handig.
Gekoppelde builds (chained builds)
Dit is wat erover wordt gezegd in in de OpenShift-documentatie:
«Twee builds kunnen aan elkaar worden gekoppeld, waarbij de ene een gecompileerde entiteit genereert en de andere deze entiteit in een aparte afbeelding plaatst, die wordt gebruikt om deze entiteit uit te voeren.»
Met andere woorden, we kunnen de Web App Builder-image gebruiken om onze build uit te voeren, en vervolgens de webserver-image, zoals NGINX, gebruiken om onze inhoud te serveren.
Op deze manier kunnen we de Web App Builder-image gebruiken als een 'schone' builder en tegelijkertijd een kleine runtime-image hebben.
Laten we dit nu bekijken met een specifiek voorbeeld.
Voor de oefening gebruiken we , gemaakt met behulp van de commandoregeltool create-react-app.
Om alles samen te voegen zal ons helpen .
Laten we dit bestand nader bekijken en beginnen met het gedeelte parameters.
parameters:
- name: SOURCE_REPOSITORY_URL
description: De bron-URL voor de applicatie
displayName: Bron-URL
required: true
- name: SOURCE_REPOSITORY_REF
description: De taknaam voor de applicatie
displayName: Bron-tak
value: master
required: true
- name: SOURCE_REPOSITORY_DIR
description: De locatie binnen de bronrepo van de applicatie
displayName: Bronmap
value: .
required: true
- name: OUTPUT_DIR
description: De locatie van de gecompileerde statische bestanden van uw webapps-bouwer
displayName: Output-map
value: build
required: false
Het is allemaal vrij duidelijk hier, maar het is belangrijk om aandacht te besteden aan de parameter OUTPUT_DIR. Voor de React-applicatie uit ons voorbeeld hoeft u zich geen zorgen te maken, omdat React als output-map de standaardwaarde gebruikt, maar voor Angular of iets anders moet deze parameter op de juiste manier worden aangepast.
Laten we nu kijken naar het gedeelte 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'
Kijk naar de derde en vierde afbeeldingen. Ze zijn beide gedefinieerd als Docker-afbeeldingen, en het is duidelijk waar ze vandaan komen.
De derde afbeelding is de web-app-builder, en deze komt uit nodeshift/ubi8-s2i-web-app met tag 10.x op .
De vierde afbeelding is de NGINX-afbeelding (versie 1.12) met tag latest op .
Laten we nu kijken naar de eerste twee afbeeldingen. Beide zijn leeg bij de start en worden alleen tijdens de bouwfase aangemaakt. De eerste afbeelding, react-web-app-builder, wordt het resultaat van de assemblagefase, die de web-app-builder-runtime afbeelding en onze broncode combineert. Daarom hebben we '-builder' aan de naam van deze afbeelding toegevoegd.
De tweede afbeelding, react-web-app-runtime, is het resultaat van de combinatie van nginx-image-runtime en enkele bestanden van de react-web-app-builder afbeelding. Deze afbeelding zal ook worden gebruikt tijdens de implementatie en zal alleen de webserver en de statische HTML, JavaScript, CSS van onze applicatie bevatten.
Verwarrend? Laten we nu kijken naar de bouwconfiguraties en het zal iets duidelijker worden.
In onze sjabloon zijn er twee bouwconfiguraties. Hier is de eerste, en deze is vrij standaard:
apiVersion: v1
kind: BuildConfig
metadata:
name: react-web-app-builder
spec:
output:
to:
kind: ImageStreamTag
name: react-web-app-builder:latest
source:
git:
uri: ${SOURCE_REPOSITORY_URL}
ref: ${SOURCE_REPOSITORY_REF}
contextDir: ${SOURCE_REPOSITORY_DIR}
type: Git
strategy:
sourceStrategy:
env:
- name: OUTPUT_DIR
value: ${OUTPUT_DIR}
from:
kind: ImageStreamTag
name: web-app-builder-runtime:latest
incremental: true
type: Source
triggers:
- github:
secret: ${GITHUB_WEBHOOK_SECRET}
type: GitHub
- type: ConfigChange
- imageChange: {}
type: ImageChange
Zoals te zien is, zegt de regel met label 1 dat het resultaat van deze bouw zal worden opgeslagen in het beeld react-web-app-builder, dat we eerder in de sectie ImageStreams hebben gezien.
De regel met label 2 geeft aan waar de code vandaan komt. In ons geval is dit een git-repository, en de locatie, ref en contextdirectory zijn gedefinieerd door de parameters die we hierboven al hebben gezien.
De regel met label 3 hebben we eerder gezien in de sectie parameters. Deze voegt de omgevingsvariabele OUTPUT_DIR toe, die in ons voorbeeld gelijk is aan build.
De regel met label 4 zegt dat we het beeld web-app-builder-runtime willen gebruiken, dat we al hebben gezien in de sectie ImageStreams.
De regel met label 5 geeft aan dat we een incrementele build willen gebruiken, mits de S2I-image dit ondersteunt, wat het beeld Web App Builder doet. Bij de eerste uitvoering, na het voltooien van de assembly-fase, zal de afbeelding de map node_modules in een archiefbestand opslaan. Bij daaropvolgende uitvoeringen zal de afbeelding deze map gewoon weer uitpakken om de bouwtijd te verkorten.
En ten slotte, de regel met label 6 zijn slechts enkele triggers zodat de bouw automatisch wordt gestart, zonder handmatige tussenkomst, wanneer er iets verandert.
Over het algemeen is dit een vrij standaard bouwconfiguratie.
Laten we nu eens kijken naar de tweede bouwconfiguratie. Deze lijkt erg op de eerste, maar er is één belangrijk verschil.
apiVersion: v1
kind: BuildConfig
metadata:
name: react-web-app-runtime
spec:
output:
to:
kind: ImageStreamTag
name: react-web-app-runtime:latest
source:
type: Image
images:
- from:
kind: ImageStreamTag
name: react-web-app-builder:latest
paths:
- sourcePath: /opt/app-root/output/.
destinationDir: .
strategy:
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
Dus, de tweede configuratie is react-web-app-runtime, en die begint vrij standaard.
In de regel met label 1 is er niets nieuws – deze zegt gewoon dat de uitkomst van de build in de afbeelding react-web-app-runtime wordt geplaatst.
De regel met label 2, zoals in de vorige configuratie, geeft aan waar de broncode vandaan komt. Maar let op dat we hier zeggen dat deze uit een afbeelding komt. En wel uit de afbeelding die we zojuist hebben gemaakt – uit react-web-app-builder (vermeld in de regel met label 3). De bestanden die we willen gebruiken, bevinden zich binnen de afbeelding en hun locatie daar wordt bepaald in de regel met label 4, in ons geval is dat /opt/app-root/output/. Als je het je herinnert, daar worden de bestanden opgeslagen die zijn gegenereerd als resultaat van de build van onze applicatie.
De doelmap, ingesteld in de regel met label 5 – is gewoon de huidige catalogus (dit draait allemaal, laten we niet vergeten, binnen een soort magische machine genaamd OpenShift, en niet op jouw lokale computer).
De sectie strategy – regel met label 6 – lijkt ook op de eerste buildconfiguratie. Maar deze keer gaan we nginx-image-runtime gebruiken, dat we al in de sectie ImageStream hebben gezien.
Tenslotte is de regel met label 7 de triggersectie die deze build activeert elke keer wanneer de afbeelding react-web-app-builder verandert.
Verder bevat deze sjabloon een vrij standaard configuratie voor implementatie, evenals elementen die betrekking hebben op diensten en routes, maar we zullen daar niet dieper op ingaan. Let op dat de afbeelding die geïmplementeerd zal worden– de afbeelding react-web-app-runtime is.
Implementatie van de applicatie
Dus, nadat we naar de sjabloon hebben gekeken, laten we eens kijken hoe we deze kunnen gebruiken om de applicatie te implementeren.
We kunnen de clienttool OpenShift genaamd oc gebruiken om onze sjabloon te implementeren:
$ 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
De eerste opdracht op de afbeelding hierboven is een opzettelijk technische manier om de sjabloon /openshiftio/application.yaml te vinden.
De tweede opdracht maakt gewoon een nieuwe applicatie op basis van deze sjabloon.
Nadat deze opdrachten zijn uitgevoerd, zullen we zien dat we twee builds hebben ontvangen:

En door terug te keren naar het overzichtsscherm, zien we de gestartte pod:

Een klik op de link – en we worden doorgestuurd naar onze applicatie, die een standaard React App-pagina is:

Aanvulling 1
Voor Angular-liefhebbers hebben we ook .
De sjabloon is hier hetzelfde, behalve de variabele OUTPUT_DIR.
Aanvulling 2
In dit artikel hebben we NGINX als webserver gebruikt, maar het is vrij eenvoudig om het te vervangen door Apache, gewoon door het sjabloonbestand aan te passen. en een werkende opdracht krijgen. .
Conclusie
In het eerste deel van deze serie hebben we laten zien hoe je moderne webapplicaties snel kunt implementeren op het OpenShift-platform. Vandaag hebben we bekeken wat de Web App afbeelding doet en hoe deze kan worden gecombineerd met een lichte webserver zoals NGINX met behulp van gekoppelde builds (chained builds) om een productiegeschikte applicatie-build te organiseren. In het volgende, afsluitende artikel van deze serie, zullen we laten zien hoe je een ontwikkelserver voor je applicatie op OpenShift kunt draaien en de synchronisatie tussen lokale en externe bestanden kunt waarborgen.
Inhoud van deze artikelenserie
- Deel 1: ;
- Deel 2: hoe de nieuwe S2I afbeelding toe te passen samen met een bestaande HTTP-server afbeelding, zoals NGINX, met behulp van gekoppelde OpenShift builds voor het organiseren van productie-implementaties;
- Deel 3: hoe een ontwikkelserver voor je applicatie op het OpenShift-platform te draaien en deze te synchroniseren met het lokale bestandssysteem.
Aanvullende bronnen
- Gratis e-boek .
- Informatie over .
Bron: habr.com
