Cześć wszystkim! Oto drugi wpis z naszej serii, w której pokazujemy, jak wdrażać nowoczesne aplikacje internetowe na Red Hat OpenShift.

W poprzednim poście nieco omówiliśmy możliwości nowego obrazu buildera S2I (source-to-image), który jest przeznaczony do budowania i wdrażania nowoczesnych aplikacji internetowych na platformie OpenShift. Wtedy interesował nas temat szybkiego wdrażania aplikacji, a dzisiaj przyjrzymy się, jak używać obrazu S2I jako „czystego” obrazu buildera i łączyć go z powiązanymi kompilacjami OpenShift.
Czysty obraz buildera
Jak wspomnieliśmy w pierwszej części, większość nowoczesnych aplikacji internetowych ma tak zwany etap budowy, na którym zazwyczaj przeprowadza się takie operacje jak transpilejsja kodu, konkatenacja kilku plików oraz minifikacja. Pliki powstałe w wyniku tych operacji – a więc statyczny HTML, JavaScript i CSS – są umieszczane w folderze output. Miejsce tego folderu zazwyczaj zależy od tego, jakie narzędzia budowania są używane, a dla React będzie to folder . /build (wrócimy do tego tematu dokładniej poniżej).
Source-to-Image (S2I)
W tym poście w ogóle nie poruszamy tematu „czym jest S2I i jak go używać” (więcej na ten temat można przeczytać ), ale ważne jest, aby wyraźnie rozumieć dwa etapy tego procesu, aby zrozumieć, co właściwie robi obraz Web App Builder.
Etap assemblacji (assemble phase)
Etap assemblacji jest w gruncie rzeczy bardzo podobny do tego, co dzieje się, gdy uruchamiasz docker build i w wyniku tego otrzymujesz nowy obraz Docker. Odpowiednio, ten etap ma miejsce przy uruchomieniu budowy na platformie OpenShift.
W przypadku obrazu Web App Builder za instalację zależności Twojej aplikacji i uruchomienie budowy odpowiada . Domyślnie obraz buildera używa konstrukcji npm run build, ale można ją nadpisać za pomocą zmiennej środowiskowej NPM_BUILD.
Jak mówiliśmy wcześniej, lokalizacja gotowej, już zbudowanej aplikacji zależy od używanych narzędzi. Na przykład, w przypadku React będzie to folder. /build, a dla aplikacji Angular – folder project_name /dist. I, jak już pokazano w poprzednim wpisie, lokalizację katalogu wyjściowego, który domyślnie jest ustawiony jako build, można nadpisać przez zmienną środowiskową OUTPUT_DIR. Ponieważ lokalizacja katalogu wyjściowego różni się w zależności od frameworka, po prostu kopiujesz wygenerowane wyjście do standardowego folderu w obrazie, a mianowicie do /opt /apt-root /output. To jest ważne dla zrozumienia dalszej części tego artykułu, a teraz szybko przejdźmy do następnego etapu – fazy uruchomienia (run phase).
Faza uruchomienia (run phase)
Ten etap zachodzi, gdy dla nowego obrazu, stworzonego w etapie składania, wywoływane jest docker run. Dzieje się to także podczas wdrażania na platformie OpenShift. Domyślnie używa do obsługi statycznych treści znajdujących się w wcześniej wspomnianym standardowym katalogu wyjściowym.
Ta metoda jest dobra do szybkiego wdrażania aplikacji, ale w rzeczywistości nie zaleca się obsługi statycznych treści w ten sposób. Ponieważ w rzeczywistości obsługujemy tylko statyczne treści, zainstalowany w obrazie Node.js nie jest potrzebny – wystarczy serwer WWW.
Mówiąc inaczej, podczas budowy potrzebujemy czegoś innego, a podczas wykonywania czegoś innego. W takiej sytuacji przydadzą się powiązane budowy (chained builds).
Powiązane budowy (chained builds)
Oto, co mówi się o w dokumentacji OpenShift:
„Dwie budowy można powiązać ze sobą, przy czym jedna z nich generuje skompilowany byt, a druga umieszcza ten byt w osobnym obrazie, który jest używany do uruchomienia tego bytu.”
Innymi słowy, możemy wykorzystać obraz Web App Builder do uruchomienia naszej budowy, a następnie użyć obrazu serwera WWW, tego samego NGINX, aby obsługiwać naszą treść.
W ten sposób możemy stosować obraz Web App Builder jako 'czysty' builder i jednocześnie mieć mały obraz runtime.
Teraz omówmy to na konkretnym przykładzie.
Do ćwiczeń użyjemy , stworzonej za pomocą narzędzia wiersza poleceń create-react-app.
Zebrać wszystko w całość pomoże nam .
Przyjrzyjmy się bliżej temu plikowi, zaczynając od sekcji parametrów.
parametry:
- nazwa: SOURCE_REPOSITORY_URL
opis: Adres URL źródłowego dla aplikacji
displayName: Adres URL źródłowy
wymagane: prawda
- nazwa: SOURCE_REPOSITORY_REF
opis: Nazwa gałęzi dla aplikacji
displayName: Gałąź źródłowa
wartość: master
wymagane: prawda
- nazwa: SOURCE_REPOSITORY_DIR
opis: Lokalizacja w repozytorium źródłowym aplikacji
displayName: Katalog źródłowy
wartość: .
wymagane: prawda
- nazwa: OUTPUT_DIR
opis: Lokalizacja skompilowanych plików statycznych z Twojego narzędzia do tworzenia aplikacji internetowych
displayName: Katalog wyjściowy
wartość: build
wymagane: fałsz
Tutaj wszystko jest dość jasne, ale warto zwrócić uwagę na parametr OUTPUT_DIR. W przypadku aplikacji React z naszego przykładu nie ma się czym martwić, ponieważ React używa domyślnego ustawienia jako katalogu wyjściowego, ale w przypadku Angulara lub innych frameworków ten parametr będzie trzeba dostosować.
Teraz przyjrzyjmy się sekcji ImageStream.
- 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'
Spójrz na trzeci i czwarty obraz. Oba zostały zdefiniowane jako obrazy Docker i widać wyraźnie, skąd pochodzą.
Trzeci obraz to web-app-builder, który pochodzi z nodeshift/ubi8-s2i-web-app z tagiem 10.x na .
Czwarty obraz to obraz NGINX (wersja 1.12) z tagiem latest na .
Teraz popatrzmy na dwa pierwsze obrazy. Oba zaczynają jako puste i są tworzone dopiero w fazie budowy. Pierwszy obraz – react-web-app-builder – będzie wynikiem etapu łączenia, który połączy obraz web-app-builder-runtime z naszym kodem źródłowym. Dlatego dodaliśmy do nazwy tego obrazu „-builder”.
Drugi obraz – react-web-app-runtime – będzie wynikiem połączenia nginx-image-runtime oraz pewnych plików z obrazu react-web-app-builder. Obraz ten również będzie używany podczas wdrożenia i będzie zawierał tylko serwer WWW oraz statyczny HTML, JavaScript, CSS naszej aplikacji.
Zawiłe? Spójrzmy teraz na konfiguracje budowy, aby stało się to trochę jaśniejsze.
W naszym szablonie znajduje się dwie konfiguracje budowy. Oto pierwsza z nich, która jest dość standardowa:
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
Jak widzimy, linia z etykietą 1 mówi, że wynik tej budowy zostanie umieszczony w obrazie react-web-app-builder, który wcześniej widzieliśmy w sekcji ImageStream.
Linia z etykietą 2 mówi, skąd brać kod. W naszym przypadku jest to repozytorium git, a lokalizacja, ref i folder kontekstowy są określone przez parametry, które już widzieliśmy powyżej.
Linia z etykietą 3 – to już widzieliśmy w sekcji parametrów. Dodaje zmienną środowiskową OUTPUT_DIR, która w naszym przykładzie ma wartość build.
Linia z etykietą 4 mówi, aby używać obrazu web-app-builder-runtime, który już widzieliśmy w sekcji ImageStream.
Linia z etykietą 5 mówi, że chcemy korzystać z inkrementalnej budowy, jeżeli obraz S2I to wspiera, a obraz Web App Builder – wspiera. Przy pierwszym uruchomieniu, po zakończeniu etapu kompilacji, obraz zachowa folder node_modules w archiwum. Następnie przy kolejnych uruchomieniach obraz po prostu rozpakowuje ten folder, aby skrócić czas budowy.
I w końcu, linia z etykietą 6 – to tylko kilka wyzwalaczy, aby budowa uruchamiała się automatycznie, bez ręcznej interwencji, gdy cokolwiek się zmienia.
Ogólnie rzecz biorąc, to dość standardowa konfiguracja budowy.
Teraz przyjrzyjmy się drugiej konfiguracji budowy. Jest ona bardzo podobna do pierwszej, ale istnieje jedna ważna różnica.
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
Więc druga konfiguracja kompilacji – react-web-app-runtime, rozpoczyna się dość standardowo.
W linii oznaczonej jako 1 nie ma nic nowego – po prostu informuje, że wynik kompilacji jest umieszczany w obrazie react-web-app-runtime.
Linia oznaczona jako 2, jak w poprzedniej konfiguracji, wskazuje, skąd pobrać kod źródłowy. Zauważcie jednak, że mówimy, iż pochodzi z obrazu. A dokładniej z obrazu, który właśnie stworzyliśmy – z react-web-app-builder (wskazany w linii oznaczonej jako 3). Pliki, które chcemy użyć, znajdują się wewnątrz obrazu, a ich lokalizacja jest określona w linii oznaczonej jako 4, w naszym przypadku to /opt/app-root/output/. Jeśli pamiętacie, tam właśnie trafiają pliki generowane w wyniku kompilacji naszej aplikacji.
Folder docelowy, określony w linii oznaczonej jako 5 – to po prostu bieżący katalog (wszystko to, przypomnijmy, kręci się wewnątrz pewnej magicznej rzeczy o nazwie OpenShift, a nie na waszym lokalnym komputerze).
Sekcja strategy – linia oznaczona jako 6 – również przypomina pierwszą konfigurację kompilacji. Tylko tym razem zamierzamy użyć nginx-image-runtime, który już widzieliśmy w sekcji ImageStream.
Wreszcie linia oznaczona jako 7 – to sekcja triggerów, która aktywuje tę kompilację za każdym razem, gdy zmienia się obraz react-web-app-builder.
Poza tym, szablon ten zawiera całkiem standardową konfigurację wdrożenia, a także rzeczy odnoszące się do usług i tras, ale nie będziemy się w to zagłębiać. Zauważcie, że obraz, który będzie wdrażany – to obraz react-web-app-runtime.
Rozwój aplikacji
Zatem, po tym jak przyjrzeliśmy się szablonowi, zobaczmy, jak go użyć do wdrożenia aplikacji.
Możemy użyć narzędzia klienckiego OpenShift o nazwie oc, aby wdrożyć nasz szablon:
$ 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
Pierwsza komenda na zrzucie powyżej – to celowo inżynierski sposób na znalezienie szablonu ./openshiftio/application.yaml.
Druga komenda po prostu tworzy nową aplikację na podstawie tego szablonu.
Po tym, jak te komendy zostaną wykonane, zobaczymy, że mamy dwie kompilacje:

A wracając do ekranu Overview, zobaczymy uruchomiony kontener:

Kliknięcie w link – przeprowadzi nas do naszej aplikacji, która jest domyślną stroną aplikacji React App:

Dodatek 1
Dla miłośników Angular również mamy .
Szablon jest taki sam, z wyjątkiem zmiennej OUTPUT_DIR.
Dodatek 2
W tym artykule użyliśmy NGINX jako serwera WWW, ale można go łatwo zamienić na Apache, po prostu zmieniając plik szablonu. na .
Podsumowanie
W pierwszej części tej serii pokazaliśmy, jak szybko wdrażać nowoczesne aplikacje webowe na platformie OpenShift. Dziś przyjrzeliśmy się, co robi obraz aplikacji webowej i jak można go połączyć z czystym serwerem WWW typu NGINX za pomocą powiązanych budów (chained build), aby zorganizować bardziej odpowiednią do warunków produkcyjnych budowę aplikacji. W następnej, końcowej części tej serii pokażemy, jak uruchomić na OpenShift serwer deweloperski dla swojej aplikacji i zapewnić synchronizację plików lokalnych i zdalnych.
Spis treści tej serii artykułów
- Część 1: ;
- Część 2: jak zastosować nowy obraz S2I razem z istniejącym obrazem serwera HTTP, na przykład NGINX, używając powiązanych budów OpenShift, aby zorganizować wdrożenie produkcyjne;
- Część 3: jak uruchomić na platformie OpenShift serwer deweloperski dla swojej aplikacji i zsynchronizować go z lokalnym systemem plików.
Dodatkowe zasoby
- Darmowa e-książka .
- Informacje na temat .
Źródło: habr.com
