Здравейте! Представяме ви втория пост от нашата серия, в която показваме как да разгръщате съвременни уеб приложения на Red Hat OpenShift.

В предишния пост леко засегнахме възможностите на новия builder образ S2I (source-to-image), който е предназначен за изграждане и разгръщане на съвременни уеб приложения на платформата OpenShift. Тогава обсъждахме как да разгръщаме приложение бързо, а днес ще разгледаме как да използвате S2I образа като „чист“ builder образ и да го комбинирате с взаимосвързани сборки на OpenShift.
Чист builder образ
Както споменахме в първата част, повечето съвременни уеб приложения имат така наречения етап на изграждане, на който обикновено се извършват операции като транспилация на кода, конкатенация на няколко файла и минификация. Получените в резултат на тези операции файлове – това са статичен HTML, JavaScript и CSS – се съхраняват в output папката. Местоположението на тази папка обикновено зависи от това какви инструменти за изграждане се използват, а за React това ще бъде папката ./build (по-подробно ще се върнем на този въпрос по-долу).
Source-to-Image (S2I)
В този пост изобщо не разглеждаме темата „какво е S2I и как да го използваме“ (повече информация можете да прочетете ), но е важно ясно да си представите два етапа на този процес, за да разберете какво точно прави образът Web App Builder.
Етап на асемблиране (assemble phase)
Етапът на асемблиране по същество е много подобен на това, което се случва, когато стартирате docker build и в резултат получавате нов Docker образ. Съответно, този етап възниква при стартиране на сборка на платформата OpenShift.
В случая на образа Web App Builder, за инсталирането на зависимостите на вашето приложение и стартиране на сборката отговаря . По подразбиране builder образът използва конструкцията npm run build, но тя може да бъде преопределена чрез променливата на средата NPM_BUILD.
Както споменахме по-рано, местоположението на готовото, вече събрано приложение зависи от инструментите, които се използват. Например, в случая с React, това ще бъде папката ./build, а за приложенията Angular – папката project_name/dist. И както беше показано в предишния пост, местоположението на output каталога, който по подразбиране е зададен като build, може да се преопредели чрез променливата на средата OUTPUT_DIR. И тъй като местоположението на output папката се различава от фреймворк до фреймворк, просто копирате генерирания output в стандартната папка в образа, а именно в /opt/apt-root/output. Това е важно за разбирането на следващата част от тази статия, а засега нека бързо разгледаме следващия етап – фазата на изпълнение (run phase).
Фаза на изпълнение (run phase)
Тази фаза настъпва, когато за новия образ, създаден в етапа на сглобяване, се извиква docker run. Тя се случва и при разгръщане на платформата OpenShift. По подразбиране използва за обслужване на статично съдържание, намиращо се в посочения по-горе стандартен output каталог.
Този метод е добър за бързо разгръщане на приложения, но само по себе си не е препоръчително да се обслужва статично съдържание по този начин. Тъй като всъщност ние обслужваме само статично съдържание, инсталираният в нашия образ Node.js не е необходим – достатъчен е и уеб сървър.
С други думи, при сглобяване ни трябва едно, а при изпълнение – друго. В такава ситуация могат да бъдат полезни свързаните сборки (chained builds).
Свързани сборки (chained builds)
Ето какво пише за в документацията на OpenShift:
«Две сборки могат да бъдат свързани помежду си, като едната генерира компилирана единица, а другата поставя тази единица в отделен образ, който се използва за стартиране на тази единица».
С други думи, можем да използваме образа Web App Builder за стартиране на нашата сборка, а след това да използваме образа на уеб сървъра, същият NGINX, за да обслужваме нашето съдържание.
По този начин можем да прилагаме образа Web App Builder като «чист» builder и да имаме малък по размер runtime образ.
Сега ще разгледаме това с конкретен пример.
За упражнение ще използваме , създадено с помощта на инструмента команден ред create-react-app.
Да съберем всичко заедно ще ни помогне .
Нека разгледаме файла по-подробно, като започнем с раздела за параметрите.
параметри:
- име: SOURCE_REPOSITORY_URL
описание: Източникът на URL за приложението
displayName: URL на източника
задължително: да
- име: SOURCE_REPOSITORY_REF
описание: Името на клон за приложението
displayName: Източен клон
стойност: master
задължително: да
- име: SOURCE_REPOSITORY_DIR
описание: Местоположението в източника на репото на приложението
displayName: Източна директория
стойност: .
задължително: да
- име: OUTPUT_DIR
описание: Местоположението на компилираните статични файлове от вашия строител на уеб приложения
displayName: Изходна директория
стойност: build
задължително: не
Тук всичко е доста ясно, но е важно да се обърне внимание на параметъра OUTPUT_DIR. За React приложението от примера ни, няма причина за притеснение, тъй като React използва стойността по подразбиране за изходна папка, но в случай с Angular или нещо друго, този параметър ще трябва да бъде променен съответно.
Сега да разгледаме раздела за 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'
Погледнете третия и четвъртия образ. И двата са определени като Docker образи и ясно се вижда откъде идват.
Третият образ – web-app-builder, и той идва от nodeshift\/ubi8-s2i-web-app с етикет 10.x на .
Четвъртият – образът на NGINX (версия 1.12) с етикет latest на .
Сега погледнете двата първи образа. Те са и двамата празни в началото и се създават само на етапа на сглобяване (build phase). Първият образ – react-web-app-builder – ще бъде резултат от етапа на асемблиране, който ще комбинира образа web-app-builder-runtime и нашия изходен код. Именно затова включихме в името на този образ «-builder».
Вторият образ – react-web-app-runtime – ще бъде резултат от комбинирането на nginx-image-runtime и някои файлове от образа react-web-app-builder. Този образ ще се използва и при разгръщането и ще съдържа само уеб сървър и статичен HTML, JavaScript, CSS на нашето приложение.
Заплетено ли е? Нека погледнем конфигурациите за сглобяване и това ще стане малко по-ясно.
В нашия шаблон има две конфигурации за сглобяване. Ето първата от тях, която е доста стандартна:
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
Както виждаме, редът с етикет 1 показва, че резултатът от това изграждане ще бъде поставен в именно този образ react-web-app-builder, който преди малко видяхме в секцията ImageStreams.
Редът с етикет 2 указва откъде ще взимаме кода. В нашия случай това е git репозиторият, а местоположението, ref и папката за контекст са определени с параметри, които вече видяхме по-горе.
Редът с етикет 3 – това вече видяхме в секцията parameters. Той добавя променлива на средата OUTPUT_DIR, която в нашия пример е равна на build.
Редът с етикет 4 указва да се използва образът web-app-builder-runtime, който вече видяхме в секцията ImageStream.
Редът с етикет 5 показва, че искаме да използваме инкрементално изграждане, ако S2I-образът го поддържа, а образът Web App Builder – поддържа. При първоначалното стартиране, след завършване на етапа на асемблиране, образът ще запази папката node_modules в архивен файл. След това, при последващите стартирания, образът просто ще разархивира тази папка, за да съкрати времето за изграждане.
И накрая, редът с етикет 6 – това е просто няколко тригери, за да може изграждането да се стартира автоматично, без нужда от ръчно намеса, когато нещо се променя.
По принцип, това е доста стандартна конфигурация за изграждане.
Сега да погледнем втората конфигурация за изграждане. Тя е много подобна на първата, но има едно съществено различие.
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
И така, втората конфигурация на сборката – react-web-app-runtime, и тя започва напълно стандартно.
В реда с етикет 1 няма нищо ново – той просто казва, че резултатът от сборката се поставя в образа react-web-app-runtime.
Редът с етикет 2, както в предишната конфигурация, посочва откъде да се вземе изходният код. Но обърнете внимание, че тук казваме, че той се взема от образа. Всъщност, от този образ, който току-що създадохме – от react-web-app-builder (посочен в реда с етикет 3). Файловете, които искаме да използваме, се намират в образа и тяхното местоположение там се задава в реда с етикет 4, в нашия случай това е /opt/app-root/output/. Ако помните, точно там се поставят файловете, генерирани в резултат на сборката на нашето приложение.
Папката за дестинация, зададена в срока с етикет 5 – е просто текущата директория (всичко това, да напомним, работи вътре в нещо магично, наречено OpenShift, а не на вашия локален компютър).
Секцията strategy – редът с етикет 6 – също е подобна на първата конфигурация на сборката. Само че този път смятаме да използваме nginx-image-runtime, който вече видяхме в раздела ImageStream.
Накрая, редът с етикет 7 – това е разделът с тригерите, който активира тази сборка всеки път, когато се променя образът react-web-app-builder.
В останалото този шаблон съдържа напълно стандартна конфигурация за разгръщане, както и неща, свързани със услуги и маршрути, но няма да задълбаваме в това. Обърнете внимание, че образът, който ще се разгръща – е образът react-web-app-runtime.
Разгръщане на приложението
И така, след като разгледахме шаблона, нека видим как да го използваме за разгръщане на приложението.
Можем да използваме клиентския инструмент OpenShift, наречен oc, за да разгръщаме нашия шаблон:
$ 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
Първата команда на екрана по-горе – е нарочно инженерният начин за намиране на шаблона ./openshiftio/application.yaml.
Втората команда просто създава ново приложение на базата на този шаблон.
След като тези команди работят, ще видим, че имаме две сборки:

А връщайки се на екрана Overview, ще видим стартирал под:

Щракването върху връзката – и ще преминем към нашето приложение, което представлява стандартната страница на приложението React App:

Добавление 1
За любителите на Angular също имаме .
Шаблонът тук е същият с изключение на променливата OUTPUT_DIR.
Добавление 2
В тази статия използвахме NGINX като уеб сървър, но е доста лесно да го замените с Apache, просто сменете файла на шаблона на .
Заключение
В първата част на тази серия показахме как бързо да разгръщате съвременни уеб приложения на платформата OpenShift. Днес разгледахме какво прави образа на уеб приложението и как може да се комбинира с чист уеб-сървър като NGINX с помощта на свързани билдове (chained builds) за осигуряване на по-подходяща за производствени условия билд на приложения. В следващата, заключителна статия от тази серия, ще покажем как да стартирате на OpenShift сървър за разработка за вашето приложение и да осигурите синхронизация между локални и отдалечени файлове.
Съдържание на тази серия статии
- Част 1: ;
- Част 2: как да приложите новия образ S2I заедно с вече съществуващия образ на HTTP-сървър, например NGINX, използвайки свързани билдове на OpenShift, за организиране на производствено разгръщане;
- Част 3: как да стартирате на платформата OpenShift сървър за разработка за вашето приложение и да го синхронизирате с локалната файлова система.
Допълнителни ресурси
- Безплатна електронна книга .
- Информация за .
Източник: habr.com
