{"id":90874,"date":"2020-08-07T01:42:20","date_gmt":"2020-08-06T23:42:20","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-2-svyazannye-sborki-chained-builds"},"modified":"2020-08-07T01:42:20","modified_gmt":"2020-08-06T23:42:20","slug":"sovremennye-prilozheniya-na-openshift-chast-2-svyazannye-sborki-chained-builds","status":"publish","type":"post","link":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-2-svyazannye-sborki-chained-builds","title":{"rendered":"Moderne applicaties op OpenShift, deel 2: chained builds","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Hallo allemaal! Dit is de tweede post in onze serie waarin we laten zien hoe je moderne webapplicaties op Red Hat OpenShift kunt implementeren. <\/p>\n<p><img decoding=\"async\" alt=\"Moderne applicaties op OpenShift, deel 2: chained builds\" src=\"\/wp-content\/uploads\/2020\/08\/b1f6ae855a69597c6e86c5198e4a628c.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn 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.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3>Schone builder-afbeelding<\/h3>\n<p>\nZoals 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 \u2013 dat zijn statische HTML, JavaScript en CSS \u2013 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).<\/p>\n<h4>Source-to-Image (S2I)<\/h4>\n<p>\nIn deze post behandelen we helemaal niet het onderwerp 'wat is S2I en hoe gebruik je het' (hierover kun je meer lezen <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.okd.io\/latest\/architecture\/core_concepts\/builds_and_image_streams.html#source-build\">hier<\/a><\/noindex>), 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.<\/p>\n<h4>Assemblagefase<\/h4>\n<p>\nDe 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.<\/p>\n<p>In het geval van de Web App Builder-afbeelding is het <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/bucharest-gold\/centos7-s2i-web-app\/blob\/master\/s2i\/assemble#L47\">assemble script<\/a><\/noindex>. standaard gebruikt de builder-afbeelding de constructie npm run build, maar deze kan worden overschreven via de omgevingsvariabele NPM_BUILD.<\/p>\n<p>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\u00ebren 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 \u2013 de uitvoeringsfase (run phase).<\/p>\n<h4>Uitvoeringsfase (run phase)<\/h4>\n<p>\nDeze 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 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/bucharest-gold\/centos7-s2i-web-app\/blob\/master\/s2i\/run\">run script<\/a><\/noindex> gebruikt <noindex><a rel=\"nofollow\" href=\"https:\/\/www.npmjs.com\/package\/serve\">serve module<\/a><\/noindex> voor het serveren van statische inhoud, die in de hierboven genoemde standaard output-map ligt.<\/p>\n<p>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\u00efnstalleerde Node.js binnen onze afbeelding niet nodig \u2013 een webserver is voldoende.<\/p>\n<p>Met andere woorden, tijdens de assemblage hebben we \u00e9\u00e9n ding nodig, tijdens de uitvoering iets anders. In zo'n situatie zijn gekoppelde builds (chained builds) handig.<\/p>\n<h3>Gekoppelde builds (chained builds)<\/h3>\n<p>\nDit is wat erover wordt gezegd in <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.okd.io\/latest\/dev_guide\/builds\/advanced_build_operations.html#dev-guide-chaining-builds\">gekoppelde builds<\/a><\/noindex> in de OpenShift-documentatie:<\/p>\n<blockquote><p>\u00abTwee 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.\u00bb\n<\/p><\/blockquote>\n<p>\nMet 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.<\/p>\n<p>Op deze manier kunnen we de Web App Builder-image gebruiken als een 'schone' builder en tegelijkertijd een kleine runtime-image hebben.<\/p>\n<p>Laten we dit nu bekijken met een specifiek voorbeeld.<\/p>\n<p>Voor de oefening gebruiken we <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/react-web-app\">een eenvoudige React-applicatie<\/a><\/noindex>, gemaakt met behulp van de commandoregeltool create-react-app.<\/p>\n<p>Om alles samen te voegen zal ons helpen <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/react-web-app\/blob\/master\/.openshiftio\/application.yaml\">de OpenShift-sjabloonbestand<\/a><\/noindex>.<\/p>\n<p>Laten we dit bestand nader bekijken en beginnen met het gedeelte parameters.<\/p>\n<pre><code class=\"plaintext\">parameters:\n  - name: SOURCE_REPOSITORY_URL\n    description: De bron-URL voor de applicatie\n    displayName: Bron-URL\n    required: true\n  - name: SOURCE_REPOSITORY_REF\n    description: De taknaam voor de applicatie\n    displayName: Bron-tak\n    value: master\n    required: true\n  - name: SOURCE_REPOSITORY_DIR\n    description: De locatie binnen de bronrepo van de applicatie\n    displayName: Bronmap\n    value: .\n    required: true\n  - name: OUTPUT_DIR\n    description: De locatie van de gecompileerde statische bestanden van uw webapps-bouwer\n    displayName: Output-map\n    value: build\n    required: false\n<\/code><\/pre>\n<p>\nHet 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.<\/p>\n<p>Laten we nu kijken naar het gedeelte ImageStreams.<\/p>\n<pre><code class=\"plaintext\">- apiVersion: v1\n  kind: ImageStream\n  metadata:\n    name: react-web-app-builder  \/\/ 1 \n  spec: {}\n- apiVersion: v1\n  kind: ImageStream\n  metadata:\n    name: react-web-app-runtime  \/\/ 2 \n  spec: {}\n- apiVersion: v1\n  kind: ImageStream\n  metadata:\n    name: web-app-builder-runtime \/\/ 3\n  spec:\n    tags:\n    - name: latest\n      from:\n        kind: DockerImage\n        name: nodeshift\/ubi8-s2i-web-app:10.x\n- apiVersion: v1\n  kind: ImageStream\n  metadata:\n    name: nginx-image-runtime \/\/ 4\n  spec:\n    tags:\n    - name: latest\n      from:\n        kind: DockerImage\n        name: 'centos\/nginx-112-centos7:latest'\n<\/code><\/pre>\n<p>\nKijk naar de derde en vierde afbeeldingen. Ze zijn beide gedefinieerd als Docker-afbeeldingen, en het is duidelijk waar ze vandaan komen.<\/p>\n<p>De derde afbeelding is de web-app-builder, en deze komt uit nodeshift\/ubi8-s2i-web-app met tag 10.x op <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/r\/nodeshift\/ubi8-s2i-web-app\/\">Docker hub<\/a><\/noindex>.<\/p>\n<p>De vierde afbeelding is de NGINX-afbeelding (versie 1.12) met tag latest op <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/r\/centos\/nginx-112-centos7\/\">Docker hub<\/a><\/noindex>.<\/p>\n<p>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.<\/p>\n<p>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.<\/p>\n<p>Verwarrend? Laten we nu kijken naar de bouwconfiguraties en het zal iets duidelijker worden.<\/p>\n<p>In onze sjabloon zijn er twee bouwconfiguraties. Hier is de eerste, en deze is vrij standaard:<\/p>\n<pre><code class=\"plaintext\">  apiVersion: v1\n  kind: BuildConfig\n  metadata:\n    name: react-web-app-builder\n  spec:\n    output:\n      to:\n        kind: ImageStreamTag\n        name: react-web-app-builder:latest \n    source:   \n      git:\n        uri: ${SOURCE_REPOSITORY_URL}\n        ref: ${SOURCE_REPOSITORY_REF}\n      contextDir: ${SOURCE_REPOSITORY_DIR}\n      type: Git\n    strategy:\n      sourceStrategy:\n        env:\n          - name: OUTPUT_DIR \n            value: ${OUTPUT_DIR}\n        from:\n          kind: ImageStreamTag\n          name: web-app-builder-runtime:latest \n        incremental: true \n      type: Source\n    triggers: \n    - github:\n        secret: ${GITHUB_WEBHOOK_SECRET}\n      type: GitHub\n    - type: ConfigChange\n    - imageChange: {}\n      type: ImageChange\n<\/code><\/pre>\n<p>\nZoals 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.<\/p>\n<p>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.<\/p>\n<p>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.<br \/>\nDe regel met label 4 zegt dat we het beeld web-app-builder-runtime willen gebruiken, dat we al hebben gezien in de sectie ImageStreams.<\/p>\n<p>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.<\/p>\n<p>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.<\/p>\n<p>Over het algemeen is dit een vrij standaard bouwconfiguratie.<\/p>\n<p>Laten we nu eens kijken naar de tweede bouwconfiguratie. Deze lijkt erg op de eerste, maar er is \u00e9\u00e9n belangrijk verschil.<\/p>\n<pre><code class=\"plaintext\">apiVersion: v1\n  kind: BuildConfig\n  metadata:\n    name: react-web-app-runtime\n  spec:\n    output:\n      to:\n        kind: ImageStreamTag\n        name: react-web-app-runtime:latest \n    source: \n      type: Image\n      images:                              \n        - from:\n            kind: ImageStreamTag\n            name: react-web-app-builder:latest \n          paths:\n            - sourcePath: \/opt\/app-root\/output\/.  \n              destinationDir: .  \n             \n    strategy: \n      sourceStrategy:\n        from:\n          kind: ImageStreamTag\n          name: nginx-image-runtime:latest\n        incremental: true\n      type: Source\n    triggers:\n    - github:\n        secret: ${GITHUB_WEBHOOK_SECRET}\n      type: GitHub\n    - type: ConfigChange\n    - type: ImageChange\n      imageChange: {}\n    - type: ImageChange\n      imageChange:\n        from:\n          kind: ImageStreamTag\n          name: react-web-app-builder:latest\n<\/code><\/pre>\n<p>\nDus, de tweede configuratie is react-web-app-runtime, en die begint vrij standaard.<\/p>\n<p>In de regel met label 1 is er niets nieuws \u2013 deze zegt gewoon dat de uitkomst van de build in de afbeelding react-web-app-runtime wordt geplaatst.<\/p>\n<p>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 \u2013 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.<\/p>\n<p>De doelmap, ingesteld in de regel met label 5 \u2013 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).<\/p>\n<p>De sectie strategy \u2013 regel met label 6 \u2013 lijkt ook op de eerste buildconfiguratie. Maar deze keer gaan we nginx-image-runtime gebruiken, dat we al in de sectie ImageStream hebben gezien.<\/p>\n<p>Tenslotte is de regel met label 7 de triggersectie die deze build activeert elke keer wanneer de afbeelding react-web-app-builder verandert.<\/p>\n<p>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\u00efmplementeerd zal worden\u2013 de afbeelding react-web-app-runtime is.<\/p>\n<h3>Implementatie van de applicatie<\/h3>\n<p>\nDus, nadat we naar de sjabloon hebben gekeken, laten we eens kijken hoe we deze kunnen gebruiken om de applicatie te implementeren.<\/p>\n<p>We kunnen de clienttool OpenShift genaamd oc gebruiken om onze sjabloon te implementeren:<\/p>\n<pre><code class=\"plaintext\">$ find . | grep openshiftio | grep application | xargs -n 1 oc apply -f\n\n$ oc new-app --template react-web-app -p SOURCE_REPOSITORY_URL=https:\/\/github.com\/lholmquist\/react-web-app\n<\/code><\/pre>\n<p>\nDe eerste opdracht op de afbeelding hierboven is een opzettelijk technische manier om de sjabloon \/openshiftio\/application.yaml te vinden.<\/p>\n<p>De tweede opdracht maakt gewoon een nieuwe applicatie op basis van deze sjabloon.<\/p>\n<p>Nadat deze opdrachten zijn uitgevoerd, zullen we zien dat we twee builds hebben ontvangen:<\/p>\n<p><img decoding=\"async\" alt=\"Moderne applicaties op OpenShift, deel 2: chained builds\" src=\"\/wp-content\/uploads\/2020\/08\/c6b2b2fcadfcd3e5a8a2adb4eff69bf2.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>En door terug te keren naar het overzichtsscherm, zien we de gestartte pod:<\/p>\n<p><img decoding=\"async\" alt=\"Moderne applicaties op OpenShift, deel 2: chained builds\" src=\"\/wp-content\/uploads\/2020\/08\/983fab3029d222555dc13790d4a3e70f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Een klik op de link \u2013 en we worden doorgestuurd naar onze applicatie, die een standaard React App-pagina is:<\/p>\n<p><img decoding=\"async\" alt=\"Moderne applicaties op OpenShift, deel 2: chained builds\" src=\"\/wp-content\/uploads\/2020\/08\/d5b658875e0e865bf456955aaac15464.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<h3>Aanvulling 1<\/h3>\n<p>\nVoor Angular-liefhebbers hebben we ook <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/angular-web-app\">voorbeeld applicatie<\/a><\/noindex>.<\/p>\n<p>De sjabloon is hier hetzelfde, behalve de variabele OUTPUT_DIR.<\/p>\n<h3>Aanvulling 2<\/h3>\n<p>\nIn 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. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/react-web-app\/blob\/master\/.openshiftio\/application.yaml#L66\">NGINX afbeelding<\/a><\/noindex> en een werkende opdracht krijgen. <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/r\/centos\/httpd-24-centos7\/\">Apache afbeelding<\/a><\/noindex>.<\/p>\n<h3>Conclusie<\/h3>\n<p>\nIn 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.<\/p>\n<h3>Inhoud van deze artikelenserie<\/h3>\n<p><\/p>\n<ul>\n<li>Deel 1: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/redhatrussia\/blog\/511954\/\">hoe moderne webapplicaties in slechts een paar stappen te implementeren<\/a><\/noindex>;<\/li>\n<li>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;<\/li>\n<li>Deel 3: hoe een ontwikkelserver voor je applicatie op het OpenShift-platform te draaien en deze te synchroniseren met het lokale bestandssysteem.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Aanvullende bronnen<\/h3>\n<p><\/p>\n<ul>\n<li>Gratis e-boek <noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/books\/deploying-openshift\">Implementeren op OpenShift<\/a><\/noindex>.<\/li>\n<li>Informatie over <noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/topics\/kubernetes\/\">OpenShift en Kubernetes<\/a><\/noindex>.<\/li>\n<\/ul>\n<p>Bron: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/redhatrussia\/blog\/513948\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u0421 \u0432\u0430\u043c\u0438 \u0432\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u0441\u0442 \u0438\u0437 \u043d\u0430\u0448\u0435\u0439 \u0441\u0435\u0440\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a\u0430\u043a \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430 Red Hat OpenShift \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c \u043f\u043e\u0441\u0442\u0435 \u043c\u044b \u0441\u043b\u0435\u0433\u043a\u0430 \u0437\u0430\u0442\u0440\u043e\u043d\u0443\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043d\u043e\u0432\u043e\u0433\u043e builder-\u043e\u0431\u0440\u0430\u0437\u0430 S2I (source-to-image), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 OpenShift. \u0422\u043e\u0433\u0434\u0430 \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043b\u0430 \u0442\u0435\u043c\u0430 \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":90875,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-90874","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u0421 \u0432\u0430\u043c\u0438 \u0432\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u0441\u0442 \u0438\u0437 \u043d\u0430\u0448\u0435\u0439 \u0441\u0435\u0440\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a\u0430\u043a \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430 Red Hat OpenShift \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-2-svyazannye-sborki-chained-builds\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"nl_NL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0421\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 OpenShift, \u0447\u0430\u0441\u0442\u044c 2: \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 chained builds | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u0421 \u0432\u0430\u043c\u0438 \u0432\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u0441\u0442 \u0438\u0437 \u043d\u0430\u0448\u0435\u0439 \u0441\u0435\u0440\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a\u0430\u043a \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430 Red Hat OpenShift \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-2-svyazannye-sborki-chained-builds\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-08-06T23:42:20+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-08-06T23:42:20+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Moderne applicaties op OpenShift, deel 2: gekoppelde builds chained builds | ProHoster","description":"Hallo allemaal! Dit is de tweede post in onze serie waarin we laten zien hoe je moderne webapplicaties op Red Hat OpenShift kunt implementeren.","canonical_url":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-2-svyazannye-sborki-chained-builds","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"nl_NL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0421\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 OpenShift, \u0447\u0430\u0441\u0442\u044c 2: \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 chained builds | ProHoster","og:description":"\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u0421 \u0432\u0430\u043c\u0438 \u0432\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u0441\u0442 \u0438\u0437 \u043d\u0430\u0448\u0435\u0439 \u0441\u0435\u0440\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a\u0430\u043a \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430 Red Hat OpenShift \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.","og:url":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-2-svyazannye-sborki-chained-builds","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-08-06T23:42:20+00:00","article:modified_time":"2020-08-06T23:42:20+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"90874","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 12:40:03","updated":"2022-10-04 00:42:31","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/90874","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/comments?post=90874"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/90874\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media\/90875"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media?parent=90874"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/categories?post=90874"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/tags?post=90874"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}