{"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! Ecco il secondo post della nostra serie in cui mostriamo come distribuire applicazioni web moderne 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 capacit\u00e0 della nuova immagine builder S2I (source-to-image), progettata per costruire e distribuire applicazioni web moderne sulla piattaforma OpenShift. In quella occasione ci siamo concentrati sulla rapida distribuzione dell'applicazione, mentre oggi vedremo come utilizzare l'immagine S2I come immagine builder 'pulita' e combinarla con build collegate di OpenShift.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3>Builder immagine pulita<\/h3>\n<p>\nCome abbiamo accennato nella prima parte, la maggior parte delle applicazioni web moderne ha una cosiddetta fase di assemblaggio, in cui vengono generalmente eseguite operazioni come la trascrizione del codice, la concatenazione di vari file e la minificazione. I file risultanti da queste operazioni \u2013 ovvero HTML statico, JavaScript e CSS \u2013 vengono collocati nella cartella output. La posizione di questa cartella dipende generalmente dagli strumenti di assemblaggio utilizzati, e per React sar\u00e0 la cartella .\/build (torneremo su questo argomento pi\u00f9 avanti).<\/p>\n<h4>Source-to-Image (S2I)<\/h4>\n<p>\nIn questo post non trattiamo affatto il tema di 'cos'\u00e8 S2I e come utilizzarlo' (puoi leggere ulteriori dettagli <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 chiara l'idea delle due fasi di questo processo per comprendere cosa fa l'immagine Web App Builder.<\/p>\n<h4>Fase di assemblaggio<\/h4>\n<p>\nLa fase di assemblaggio \u00e8 di fatto molto simile a ci\u00f2 che accade quando esegui un docker build e ottieni una nuova immagine Docker. Pertanto, questa fase si verifica quando avvii il build sulla piattaforma OpenShift.<\/p>\n<p>Nel caso dell'immagine Web App Builder, l'installazione delle dipendenze della tua applicazione e l'avvio del build sono gestiti dallo <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 accennato in precedenza, la posizione dell'applicazione 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 mostrato nel post precedente, la posizione della cartella output, impostata di default come build, pu\u00f2 essere sovrascritta tramite la variabile d'ambiente OUTPUT_DIR. Poich\u00e9 la posizione della cartella output varia a seconda del framework, \u00e8 sufficiente copiare l'output generato nella cartella standard all'interno dell'immagine, precisamente in \/opt\/apt-root\/output. Questo \u00e8 importante per comprendere la parte successiva di questo articolo, ma per ora diamo un'occhiata rapida alla fase successiva \u2013 fase di esecuzione.<\/p>\n<h4>Fase di esecuzione<\/h4>\n<p>\nQuesta fase si verifica quando viene eseguito un docker run per la nuova immagine creata nella fase di assemblaggio. Si verifica anche durante il deployment sulla piattaforma OpenShift. Di default, il <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/bucharest-gold\/centos7-s2i-web-app\/blob\/master\/s2i\/run\">script di esecuzione<\/a><\/noindex> utilizza <noindex><a rel=\"nofollow\" href=\"https:\/\/www.npmjs.com\/package\/serve\">serve module<\/a><\/noindex> gestisce i contenuti statici che si trovano nella suddetta cartella output standard.<\/p>\n<p>Questo metodo \u00e8 buono per la rapida distribuzione delle applicazioni, ma in realt\u00e0 non \u00e8 consigliabile gestire contenuti statici in questo modo. Poich\u00e9 in effetti stiamo solo servendo contenuti statici, l'installazione di Node.js all'interno della nostra immagine non \u00e8 necessaria: un semplice server web \u00e8 sufficiente.<\/p>\n<p>In altre parole, abbiamo bisogno di una cosa in fase di costruzione e di un'altra in fase di esecuzione. In questa situazione, le build collegate (chained builds) possono risultare utili.<\/p>\n<h3>Build collegate<\/h3>\n<p>\nEcco cosa dice la documentazione di OpenShift riguardo alle <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> :<\/p>\n<blockquote><p>\"Due build possono essere collegate tra loro, in cui una genera un'entit\u00e0 compilata e l'altra colloca questa entit\u00e0 in un'immagine separata, utilizzata per eseguire questa entit\u00e0.\"\n<\/p><\/blockquote>\n<p>\nIn altre parole, possiamo utilizzare l'immagine Web App Builder per eseguire la nostra build, e quindi utilizzare l'immagine del server web, come NGINX, per gestire il nostro contenuto.<\/p>\n<p>In questo modo, possiamo utilizzare l'immagine Web App Builder come builder 'pulita' e avere un'immagine runtime di dimensioni contenute.<\/p>\n<p>Ora esaminiamo un esempio concreto.<\/p>\n<p>Per fare pratica, utilizzeremo un <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/react-web-app\">semplice applicazione React<\/a><\/noindex>, creata utilizzando il tool da riga di comando create-react-app.<\/p>\n<p>Per unire tutto, il <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/react-web-app\/blob\/master\/.openshiftio\/application.yaml\">file template di OpenShift<\/a><\/noindex>.<\/p>\n<p>ci aiuter\u00e0. Analizziamo questo file pi\u00f9 nel dettaglio, partendo dalla sezione dei parametri.<\/p>\n<pre><code class=\"plaintext\">parameters:\n  - name: SOURCE_REPOSITORY_URL\n    description: The source URL for the application\n    displayName: Source URL\n    required: true\n  - name: SOURCE_REPOSITORY_REF\n    description: The branch name for the application\n    displayName: Source Branch\n    value: master\n    required: true\n  - name: SOURCE_REPOSITORY_DIR\n    description: The location within the source repo of the application\n    displayName: Source Directory\n    value: .\n    required: true\n  - name: OUTPUT_DIR\n    description: The location of the compiled static files from your web apps builder\n    displayName: Output Directory\n    value: build\n    required: false\n<\/code><\/pre>\n<p>\nQui tutto \u00e8 abbastanza chiaro, ma \u00e8 necessario 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 cartella di output il valore predefinito, ma nel caso di Angular o di qualcos'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 le terze e quarte immagini. Entrambe sono definite come immagini Docker ed \u00e8 evidente da dove provengono.<\/p>\n<p>La terza immagine \u00e8 web-app-builder, e proviene 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. Entrambe sono vuote all'inizio e vengono create solo nella fase di build. La prima immagine, react-web-app-builder, sar\u00e0 il risultato della fase di assemblaggio, che unir\u00e0 l'immagine web-app-builder-runtime e il nostro codice sorgente. \u00c8 per questo che abbiamo aggiunto \u00ab-builder\u00bb nel nome di quest'immagine.<\/p>\n<p>La seconda immagine, react-web-app-runtime, sar\u00e0 il risultato della combinazione dell'immagine nginx-image-runtime e di alcuni file dall'immagine react-web-app-builder. Quest'immagine sar\u00e0 utilizzata anche per il deployment e conterr\u00e0 solo il server web e il codice statico HTML, JavaScript, 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, che \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 vediamo, la riga contrassegnata con 1 indica che il risultato di questa build sar\u00e0 inserito nell'immagine react-web-app-builder che abbiamo visto prima nella sezione degli ImageStream.<\/p>\n<p>La riga contrassegnata con 2 indica da dove prendere il codice. Nel nostro caso, questo \u00e8 un repository git, e la posizione, il ref e la cartella di contesto sono definiti da parametri che abbiamo gi\u00e0 visto sopra.<\/p>\n<p>La riga contrassegnata con 3 \u00e8 quella che abbiamo gi\u00e0 visto nella sezione dei parametri. Aggiunge la variabile d'ambiente OUTPUT_DIR, che nel nostro esempio \u00e8 uguale a build.<br \/>\nLa riga contrassegnata con 4 indica di utilizzare l'immagine web-app-builder-runtime che abbiamo gi\u00e0 visto nella sezione degli ImageStream.<\/p>\n<p>La riga contrassegnata con 5 indica che vogliamo utilizzare un build incrementale, se l'immagine S2I lo supporta, e l'immagine Web App Builder lo fa. Al primo avvio, dopo il completamento della fase di assemblaggio, l'immagine salver\u00e0 la cartella node_modules in un file zip. Poi, nei successivi avvi, l'immagine semplicemente decomprimer\u00e0 questa cartella per ridurre il tempo di build.<\/p>\n<p>E infine, la riga contrassegnata con 6 \u00e8 solo qualche trigger per avviare automaticamente la build, senza intervento manuale, quando qualcosa cambia.<\/p>\n<p>In generale, questa \u00e8 una configurazione di build piuttosto 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 build \u00e8 react-web-app-runtime, e inizia in modo piuttosto standard.<\/p>\n<p>Nella riga contrassegnata con 1 non c'\u00e8 nulla di nuovo: dice semplicemente che il risultato della build verr\u00e0 inserito nell'immagine react-web-app-runtime.<\/p>\n<p>La riga con l'etichetta 2, come nella configurazione precedente, indica da dove prelevare il codice sorgente. Ma attenzione, qui diciamo che proviene dall'immagine. Inoltre, dall'immagine che abbiamo appena creato - da react-web-app-builder (indicata nella riga con l'etichetta 3). I file che vogliamo utilizzare si trovano all'interno dell'immagine e la loro posizione \u00e8 specificata nella riga con l'etichetta 4, nel nostro caso \u00e8 \/opt\/app-root\/output\/. Se ricordate, proprio l\u00ec vengono salvati i file generati al termine della compilazione della nostra applicazione.<\/p>\n<p>La cartella di destinazione, specificata nella riga con l'etichetta 5, \u00e8 semplicemente la directory corrente (tutto ci\u00f2, ricordiamolo, si svolge all'interno di una sorta di magia chiamata OpenShift, e non sul vostro computer locale).<\/p>\n<p>La sezione strategy - la riga con l'etichetta 6 - \u00e8 simile alla prima configurazione di compilazione. Solo che questa volta abbiamo intenzione di utilizzare nginx-image-runtime, che abbiamo gi\u00e0 visto nella sezione ImageStream.<\/p>\n<p>Infine, la riga con l'etichetta 7 \u00e8 la sezione dei trigger, che attivano questa compilazione ogni volta che l'immagine react-web-app-builder cambia.<\/p>\n<p>A parte questo, questo modello contiene una configurazione di deployment piuttosto standard, oltre ad elementi relativi ai servizi e ai percorsi, ma non approfondiremo questo aspetto. 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 modello, vediamo come utilizzarlo per distribuire un'applicazione.<\/p>\n<p>Possiamo utilizzare lo strumento client OpenShift chiamato oc, per distribuire il nostro modello:<\/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 ingegneristico per trovare il modello .\/openshiftio\/application.yaml.<\/p>\n<p>Il secondo comando semplicemente crea una nuova applicazione basata su questo modello.<\/p>\n<p>Dopo che questi comandi sono stati eseguiti, vedremo che sono state create 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 alla schermata Overview, 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 ci porter\u00e0 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 amanti 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 \u00e8 lo stesso, eccetto per la variabile OUTPUT_DIR.<\/p>\n<h3>Appendice 2<\/h3>\n<p>\nIn questo articolo abbiamo usato NGINX come server web, ma \u00e8 abbastanza facile sostituirlo con Apache, basta cambiare nel file modello <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/react-web-app\/blob\/master\/.openshiftio\/application.yaml#L66\">immagine NGINX<\/a><\/noindex> con <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 come NGINX attraverso build collegate (chained build) per organizzare una compilazione pi\u00f9 adatta alle condizioni di produzione. Nell'ultimo articolo di questa serie, mostreremo come eseguire un server di sviluppo per la nostra applicazione su OpenShift e mantenere la sincronizzazione tra i 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 semplici passaggi<\/a><\/noindex>;<\/li>\n<li>Parte 2: come applicare la nuova immagine S2I insieme a un'immagine HTTP server esistente, come NGINX, usando build collegate di OpenShift per organizzare distribuzioni in produzione;<\/li>\n<li>Parte 3: come avviare un server di sviluppo per la propria applicazione sulla piattaforma OpenShift e sincronizzarlo con il file system 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\">Deploying to 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.0.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.0.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\udd47Modern applications on OpenShift, Part 2: chained builds | ProHoster","description":"Ciao a tutti! Ecco il secondo post della nostra serie in cui mostriamo come distribuire applicazioni web moderne 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}]}}