{"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\/it\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-2-svyazannye-sborki-chained-builds","title":{"rendered":"Applicazioni moderne su OpenShift, parte 2: build collegate chained builds","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Ciao a tutti! Questo \u00e8 il secondo post della nostra serie in cui mostriamo come distribuire moderne applicazioni web su Red Hat OpenShift. <\/p>\n<p><img decoding=\"async\" alt=\"Applicazioni moderne su OpenShift, parte 2: build collegate chained builds\" src=\"\/wp-content\/uploads\/2020\/08\/b1f6ae855a69597c6e86c5198e4a628c.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNel post precedente abbiamo accennato alle funzionalit\u00e0 della nuova immagine builder S2I (source-to-image), progettata per la costruzione e distribuzione di moderne applicazioni web sulla piattaforma OpenShift. Allora ci interessava il tema della rapida distribuzione delle applicazioni, mentre oggi vedremo come utilizzare l'immagine S2I come immagine builder \u00abpulita\u00bb e combinarla con le build correlate di OpenShift.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3>Immagine builder pulita<\/h3>\n<p>\nCome abbiamo menzionato nella prima parte, la maggior parte delle moderne applicazioni web ha un cosiddetto stadio di costruzione, in cui di solito vengono eseguite operazioni come la transpiling del codice, la concatenazione di pi\u00f9 file e la minificazione. I file risultanti da queste operazioni \u2013 ovvero HTML, JavaScript e CSS statici \u2013 vengono collocati nella cartella di output. La posizione di questa cartella dipende solitamente dagli strumenti di costruzione utilizzati, e per React sar\u00e0 la cartella . \/build (torneremo su questo punto pi\u00f9 avanti).<\/p>\n<h4>Source-to-Image (S2I)<\/h4>\n<p>\nIn questo post non tocchiamo affatto il tema \u00abcos'\u00e8 S2I e come usarlo\u00bb (puoi leggere di pi\u00f9 <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.okd.io\/latest\/architecture\/core_concepts\/builds_and_image_streams.html#source-build\">qui<\/a><\/noindex>), ma \u00e8 importante avere ben chiari due stadi di questo processo per comprendere cosa faccia l'immagine Web App Builder.<\/p>\n<h4>Stadio di assemblaggio (assemble phase)<\/h4>\n<p>\nLo stadio di assemblaggio \u00e8 molto simile a quello che accade quando esegui docker build e ottieni una nuova immagine Docker. Di conseguenza, questo stadio si verifica quando avvii una build sulla piattaforma OpenShift.<\/p>\n<p>Nel caso dell'immagine Web App Builder, l'installazione delle dipendenze della tua applicazione e l'avvio della build sono gestiti da <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/bucharest-gold\/centos7-s2i-web-app\/blob\/master\/s2i\/assemble#L47\">assemble script<\/a><\/noindex>. Di default, l'immagine builder utilizza la struttura npm run build, ma pu\u00f2 essere sovrascritta tramite la variabile d'ambiente NPM_BUILD.<\/p>\n<p>Come abbiamo detto in precedenza, la posizione dell'applicazione finale, gi\u00e0 assemblata, dipende dagli strumenti utilizzati. Ad esempio, nel caso di React, sar\u00e0 la cartella .\/build, mentre per le applicazioni Angular sar\u00e0 la cartella project_name\/dist. E, come gi\u00e0 mostrato nel post precedente, la posizione della cartella output, che \u00e8 impostata di default come build, pu\u00f2 essere sovrascritta mediante la variabile d'ambiente OUTPUT_DIR. E poich\u00e9 la posizione della cartella output varia da framework a framework, si copia semplicemente l'output generato nella cartella standard nell'immagine, cio\u00e8 in \/opt\/apt-root\/output. Questo \u00e8 importante per comprendere la parte successiva di questo articolo, ma per ora diamo un'occhiata rapidamente alla fase successiva: avvio (run phase).<\/p>\n<h4>Fase di avvio (run phase)<\/h4>\n<p>\nQuesta fase si verifica quando viene eseguito un comando docker run per una nuova immagine creata nella fase di assemblaggio. Si verifica anche durante il deployment sulla piattaforma OpenShift. Per impostazione predefinita <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/bucharest-gold\/centos7-s2i-web-app\/blob\/master\/s2i\/run\">run script<\/a><\/noindex> utilizza <noindex><a rel=\"nofollow\" href=\"https:\/\/www.npmjs.com\/package\/serve\">serve module<\/a><\/noindex> per servire contenuti statici presenti nella suddetta cartella output standard.<\/p>\n<p>Questo metodo \u00e8 utile per il rapido deployment delle applicazioni, ma in realt\u00e0 non \u00e8 raccomandato servire contenuti statici in questo modo. Dato che in pratica serviamo solo contenuti statici, Node.js installato all'interno della nostra immagine non \u00e8 necessario: basta un server web.<\/p>\n<p>In altre parole, durante l'assemblaggio abbiamo bisogno di una cosa, durante l'esecuzione di un'altra. In questa situazione sono utili le build collegate (chained builds).<\/p>\n<h3>Build collegate (chained builds)<\/h3>\n<p>\nEcco cosa si dice riguardo a <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.okd.io\/latest\/dev_guide\/builds\/advanced_build_operations.html#dev-guide-chaining-builds\">chained builds<\/a><\/noindex> nella documentazione di OpenShift:<\/p>\n<blockquote><p>\u00abDue build possono essere collegate tra loro, in cui una genera un'entit\u00e0 compilata e l'altra posiziona quest'entit\u00e0 in un'immagine separata, utilizzata per eseguire tale entit\u00e0\u00bb.\n<\/p><\/blockquote>\n<p>\nIn altre parole, possiamo utilizzare l'immagine Web App Builder per eseguire la nostra build, e poi utilizzare l'immagine del server web, lo stesso NGINX, per servire i nostri contenuti.<\/p>\n<p>In questo modo, possiamo utilizzare l'immagine Web App Builder come builder \u00abpulito\u00bb e avere al contempo un'immagine runtime di dimensioni ridotte.<\/p>\n<p>Ora esaminiamo questo attraverso un esempio concreto.<\/p>\n<p>Per l'esercitazione utilizzeremo <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/react-web-app\">una semplice applicazione React<\/a><\/noindex>, creata con lo strumento da riga di comando create-react-app.<\/p>\n<p>Per mettere tutto insieme ci aiuter\u00e0 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/react-web-app\/blob\/master\/.openshiftio\/application.yaml\">il file di template di OpenShift<\/a><\/noindex>.<\/p>\n<p>Esaminiamo questo file pi\u00f9 nel dettaglio e iniziamo dalla sezione dei parametri.<\/p>\n<pre><code class=\"plaintext\">parameters:\n  - name: SOURCE_REPOSITORY_URL\n    description: L'URL sorgente dell'applicazione\n    displayName: URL Sorgente\n    required: true\n  - name: SOURCE_REPOSITORY_REF\n    description: Il nome del branch dell'applicazione\n    displayName: Branch Sorgente\n    value: master\n    required: true\n  - name: SOURCE_REPOSITORY_DIR\n    description: La posizione all'interno del repository sorgente dell'applicazione\n    displayName: Directory Sorgente\n    value: .\n    required: true\n  - name: OUTPUT_DIR\n    description: La posizione dei file statici compilati dal tuo builder di applicazioni web\n    displayName: Directory di Output\n    value: build\n    required: false\n<\/code><\/pre>\n<p>\nQui tutto \u00e8 piuttosto chiaro, ma vale la pena prestare attenzione al parametro OUTPUT_DIR. Per l'applicazione React del nostro esempio non c'\u00e8 nulla di cui preoccuparsi, poich\u00e9 React utilizza come directory di output il valore predefinito, ma nel caso di Angular o di altro, questo parametro dovr\u00e0 essere modificato di conseguenza.<\/p>\n<p>Ora diamo un'occhiata alla sezione degli ImageStream.<\/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>\nGuarda il terzo e il quarto immagine. Entrambi sono definiti come immagini Docker e qui \u00e8 chiaramente visibile da dove provengono.<\/p>\n<p>La terza immagine \u00e8 web-app-builder, e viene da nodeshift\/ubi8-s2i-web-app con il tag 10.x su <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/r\/nodeshift\/ubi8-s2i-web-app\/\">Docker hub<\/a><\/noindex>.<\/p>\n<p>La quarta \u00e8 l'immagine NGINX (versione 1.12) con il tag latest su <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/r\/centos\/nginx-112-centos7\/\">Docker hub<\/a><\/noindex>.<\/p>\n<p>Ora diamo un'occhiata alle prime due immagini. Sono entrambe vuote all'inizio e vengono create solo durante la fase di build. La prima immagine \u2013 react-web-app-builder \u2013 sar\u00e0 il risultato della fase di assemblaggio, che unir\u00e0 l'immagine web-app-builder-runtime e il nostro codice sorgente. Ecco perch\u00e9 abbiamo scritto 'builder' nel nome di quest'immagine.<\/p>\n<p>La seconda immagine \u2013 react-web-app-runtime \u2013 sar\u00e0 il risultato della combinazione di nginx-image-runtime e alcuni file dall'immagine react-web-app-builder. Questa immagine sar\u00e0 utilizzata anche durante il deploy e conterr\u00e0 solo il server web e il HTML statico, JavaScript e CSS della nostra applicazione.<\/p>\n<p>Complicato? Ora diamo un'occhiata alle configurazioni di build e diventer\u00e0 un po' pi\u00f9 chiaro.<\/p>\n<p>Nel nostro template ci sono due configurazioni di build. Ecco la prima di esse, ed \u00e8 piuttosto standard:<\/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 \\\/\\\/ 1\n    source:   \\\/\\\/ 2 \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 \\\/\\\/ 3 \n            value: ${OUTPUT_DIR}\n        from:\n          kind: ImageStreamTag\n          name: web-app-builder-runtime:latest \\\/\\\/ 4\n        incremental: true \\\/\\\/ 5\n      type: Source\n    triggers: \\\/\\\/ 6\n    - github:\n        secret: ${GITHUB_WEBHOOK_SECRET}\n      type: GitHub\n    - type: ConfigChange\n    - imageChange: {}\n      type: ImageChange\n<\/code><\/pre>\n<p>\nCome possiamo vedere, la riga con l'etichetta 1 indica che il risultato di questa build sar\u00e0 collocato nell'immagine react-web-app-builder, che abbiamo visto poco prima nella sezione ImageStream.<\/p>\n<p>La riga con l'etichetta 2 indica da dove prendere il codice. Nel nostro caso si tratta di un repository git, e la posizione, il ref e la cartella di contesto sono definiti dalle variabili che abbiamo gi\u00e0 visto sopra.<\/p>\n<p>La riga con l'etichetta 3 \u2013 l'abbiamo gi\u00e0 vista nella sezione parameters. Aggiunge la variabile d'ambiente OUTPUT_DIR, che nel nostro esempio \u00e8 uguale a build.<br \/>\nLa riga con l'etichetta 4 indica di utilizzare l'immagine web-app-builder-runtime, che abbiamo gi\u00e0 visto nella sezione ImageStream.<\/p>\n<p>La riga con l'etichetta 5 indica che vogliamo utilizzare una build incrementale, se l'immagine S2I la supporta, e l'immagine Web App Builder lo supporta. Durante il primo avvio, al termine della fase di assemblaggio, l'immagine salver\u00e0 la cartella node_modules in un file di archivio. Nei successivi avvii, l'immagine decomprimer\u00e0 semplicemente questa cartella per ridurre il tempo di build.<\/p>\n<p>E infine, la riga con l'etichetta 6 \u2013 sono solo alcuni trigger, affinch\u00e9 la build si avvii automaticamente, senza intervento manuale, quando qualcosa cambia.<\/p>\n<p>In generale, si tratta di una configurazione di build abbastanza standard.<\/p>\n<p>Ora diamo un'occhiata alla seconda configurazione di build. \u00c8 molto simile alla prima, ma c'\u00e8 una differenza importante.<\/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 \\\/\\\/ 1\n    source: \\\/\\\/ 2\n      type: Image\n      images:                              \n        - from:\n            kind: ImageStreamTag\n            name: react-web-app-builder:latest \\\/\\\/ 3\n          paths:\n            - sourcePath: \\\/opt\\\/app-root\\\/output\\\/.  \\\/\\\/ 4\n              destinationDir: .  \\\/\\\/ 5\n             \n    strategy: \\\/\\\/ 6\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 \\\/\\\/ 7\n<\/code><\/pre>\n<p>\nQuindi, la seconda configurazione di compilation \u00e8 react-web-app-runtime, e inizia in modo abbastanza standard.<\/p>\n<p>Nella riga contrassegnata con 1 non c'\u00e8 nulla di nuovo: dice semplicemente che il risultato della compilazione viene messo nell'immagine react-web-app-runtime.<\/p>\n<p>La riga contrassegnata con 2, come nella configurazione precedente, indica da dove prendere il codice sorgente. Ma notate che qui diciamo che viene preso dall'immagine. Ed \u00e8 quell'immagine che abbiamo appena creato \u2013 da react-web-app-builder (indicata nella riga contrassegnata con 3). I file che vogliamo utilizzare si trovano all'interno dell'immagine e la loro posizione \u00e8 specificata nella riga contrassegnata con 4, nel nostro caso \u00e8 \/opt\/app-root\/output\/. Se ricordate, \u00e8 proprio l\u00ec che vengono messi i file generati dai risultati della compilazione della nostra applicazione.<\/p>\n<p>La cartella di destinazione, specificata nella riga contrassegnata con 5, \u00e8 semplicemente la cartella corrente (tutto questo, ricordiamo, gira all'interno di una sorta di cosa magica chiamata OpenShift, e non sul vostro computer locale).<\/p>\n<p>La sezione strategy \u2013 la riga contrassegnata con 6 \u2013 \u00e8 simile alla prima configurazione di compilation. Solo che questa volta intendiamo usare nginx-image-runtime, che abbiamo gi\u00e0 visto nella sezione ImageStream.<\/p>\n<p>Infine, la riga contrassegnata con 7 \u00e8 la sezione dei trigger che attivano questa compilazione ogni volta che cambia l'immagine react-web-app-builder.<\/p>\n<p>Per il resto, questo template contiene una configurazione di deployment piuttosto standard, cos\u00ec come elementi relativi ai servizi e ai percorsi, ma non ci andremo a soffermare. Notate che l'immagine che verr\u00e0 distribuita \u00e8 l'immagine react-web-app-runtime.<\/p>\n<h3>Distribuzione dell'applicazione<\/h3>\n<p>\nQuindi, dopo aver esaminato il template, vediamo come utilizzarlo per la distribuzione dell'applicazione.<\/p>\n<p>Possiamo usare lo strumento client di OpenShift chiamato oc per distribuire il nostro template:<\/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>\nIl primo comando nello screenshot sopra \u00e8 un modo volutamente ingegneristico per trovare il template .\/openshiftio\/application.yaml.<\/p>\n<p>Il secondo comando crea semplicemente una nuova applicazione basata su questo template.<\/p>\n<p>Dopo che questi comandi saranno stati eseguiti, vedremo che abbiamo due compilazioni:<\/p>\n<p><img decoding=\"async\" alt=\"Applicazioni moderne su OpenShift, parte 2: build collegate chained builds\" src=\"\/wp-content\/uploads\/2020\/08\/c6b2b2fcadfcd3e5a8a2adb4eff69bf2.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>E tornando allo schermo di Panoramica, vedremo il pod avviato:<\/p>\n<p><img decoding=\"async\" alt=\"Applicazioni moderne su OpenShift, parte 2: build collegate chained builds\" src=\"\/wp-content\/uploads\/2020\/08\/983fab3029d222555dc13790d4a3e70f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Un clic sul link e passeremo alla nostra applicazione, che \u00e8 una pagina dell'applicazione React App per impostazione predefinita:<\/p>\n<p><img decoding=\"async\" alt=\"Applicazioni moderne su OpenShift, parte 2: build collegate chained builds\" src=\"\/wp-content\/uploads\/2020\/08\/d5b658875e0e865bf456955aaac15464.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<h3>Supplemento 1<\/h3>\n<p>\nPer gli appassionati di Angular abbiamo anche <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/angular-web-app\">un esempio di applicazione<\/a><\/noindex>.<\/p>\n<p>Il modello qui \u00e8 lo stesso, ad eccezione della variabile OUTPUT_DIR.<\/p>\n<h3>Supplemento 2<\/h3>\n<p>\nIn questo articolo abbiamo usato NGINX come server web, ma \u00e8 piuttosto semplice sostituirlo con Apache, basta modificare il file del modello <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/react-web-app\/blob\/master\/.openshiftio\/application.yaml#L66\">immagine NGINX<\/a><\/noindex> in <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/r\/centos\/httpd-24-centos7\/\">immagine Apache<\/a><\/noindex>.<\/p>\n<h3>Conclusione<\/h3>\n<p>\nNella prima parte di questa serie abbiamo mostrato come distribuire rapidamente applicazioni web moderne sulla piattaforma OpenShift. Oggi abbiamo esaminato cosa fa l'immagine Web App e come pu\u00f2 essere combinata con un server web puro come NGINX utilizzando build collegate (chained build) per organizzare una build pi\u00f9 adatta per l'ambiente di produzione. Nel prossimo e ultimo articolo di questa serie, mostreremo come avviare un server di sviluppo per la propria applicazione su OpenShift e garantire la sincronizzazione dei file locali e remoti.<\/p>\n<h3>Contenuto di questa serie di articoli<\/h3>\n<p><\/p>\n<ul>\n<li>Parte 1: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/redhatrussia\/blog\/511954\/\">come distribuire applicazioni web moderne in pochi passaggi<\/a><\/noindex>;<\/li>\n<li>Parte 2: come applicare una nuova immagine S2I insieme a un'immagine HTTP server esistente, come NGINX, utilizzando build collegate di OpenShift, per organizzare una distribuzione per la produzione;<\/li>\n<li>Parte 3: come avviare un server di sviluppo per la propria applicazione sulla piattaforma OpenShift e sincronizzarlo con il filesystem locale.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Risorse aggiuntive<\/h3>\n<p><\/p>\n<ul>\n<li>Ebook gratuito <noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/books\/deploying-openshift\">Distribuzione su OpenShift<\/a><\/noindex>.<\/li>\n<li>Informazioni su <noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/topics\/kubernetes\/\">OpenShift e Kubernetes<\/a><\/noindex>.<\/li>\n<\/ul>\n<p>Fonte: <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.1.1 - 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\/it\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-2-svyazannye-sborki-chained-builds\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\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\/it\/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\udd47Applicazioni moderne su OpenShift, parte 2: build collegate chained builds | ProHoster","description":"Ciao a tutti! Questo \u00e8 il secondo post della nostra serie in cui mostriamo come distribuire moderne applicazioni web su Red Hat OpenShift.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-2-svyazannye-sborki-chained-builds","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","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\/it\/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\/it\/wp-json\/wp\/v2\/posts\/90874","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=90874"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/90874\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/90875"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=90874"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=90874"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=90874"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}