{"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\/pt\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-2-svyazannye-sborki-chained-builds","title":{"rendered":"Aplica\u00e7\u00f5es modernas no OpenShift, parte 2: constru\u00e7\u00f5es encadeadas","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Ol\u00e1 a todos! Estamos de volta com o segundo post da nossa s\u00e9rie, onde mostramos como implantar aplica\u00e7\u00f5es web modernas no Red Hat OpenShift. <\/p>\n<p><img decoding=\"async\" alt=\"Aplica\u00e7\u00f5es modernas no OpenShift, parte 2: constru\u00e7\u00f5es encadeadas\" src=\"\/wp-content\/uploads\/2020\/08\/b1f6ae855a69597c6e86c5198e4a628c.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNo post anterior, introduzimos as capacidades da nova imagem builder S2I (source-to-image), destinada \u00e0 constru\u00e7\u00e3o e implanta\u00e7\u00e3o de aplica\u00e7\u00f5es web modernas na plataforma OpenShift. Naquela ocasi\u00e3o, focamos no tema da r\u00e1pida implanta\u00e7\u00e3o de aplica\u00e7\u00f5es, e hoje veremos como usar a imagem S2I como uma imagem builder \"pura\" e combin\u00e1-la com constru\u00e7\u00f5es encadeadas do OpenShift.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3>Imagem builder pura<\/h3>\n<p>\nComo mencionamos na primeira parte, a maioria das aplica\u00e7\u00f5es web modernas possui uma chamada fase de constru\u00e7\u00e3o, onde normalmente s\u00e3o realizadas opera\u00e7\u00f5es como transpira\u00e7\u00e3o de c\u00f3digo, concatena\u00e7\u00e3o de arquivos e minifica\u00e7\u00e3o. Os arquivos resultantes dessas opera\u00e7\u00f5es \u2013 incluindo HTML est\u00e1tico, JavaScript e CSS \u2013 s\u00e3o armazenados na pasta de sa\u00edda. O local dessa pasta depende das ferramentas de constru\u00e7\u00e3o utilizadas, e para o React, ser\u00e1 a pasta .\/build (voltaremos a esse ponto mais adiante).<\/p>\n<h4>Source-to-Image (S2I)<\/h4>\n<p>\nNeste post, n\u00e3o abordaremos o tema \"o que \u00e9 S2I e como us\u00e1-lo\" (pode-se ler mais sobre isso <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.okd.io\/latest\/architecture\/core_concepts\/builds_and_image_streams.html#source-build\">aqui<\/a><\/noindex>), mas \u00e9 importante ter uma vis\u00e3o clara das duas etapas desse processo para entender o que a imagem Web App Builder realmente faz.<\/p>\n<h4>Fase de montagem (assemble phase)<\/h4>\n<p>\nA fase de montagem \u00e9 muito semelhante ao que acontece quando voc\u00ea executa um docker build e, como resultado, obt\u00e9m uma nova imagem Docker. Portanto, essa fase ocorre ao iniciar uma constru\u00e7\u00e3o na plataforma OpenShift.<\/p>\n<p>No caso da imagem Web App Builder, a instala\u00e7\u00e3o das depend\u00eancias da sua aplica\u00e7\u00e3o e o in\u00edcio da constru\u00e7\u00e3o \u00e9 responsabilidade do <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/bucharest-gold\/centos7-s2i-web-app\/blob\/master\/s2i\/assemble#L47\">script de montagem<\/a><\/noindex>. Por padr\u00e3o, a imagem builder utiliza o comando npm run build, mas isso pode ser sobrescrito atrav\u00e9s da vari\u00e1vel de ambiente NPM_BUILD.<\/p>\n<p>Como mencionamos anteriormente, a localiza\u00e7\u00e3o do aplicativo final, j\u00e1 montado, depende das ferramentas utilizadas. Por exemplo, no caso do React, ser\u00e1 a pasta .\/build, enquanto para aplicativos Angular, ser\u00e1 a pasta project_name\/dist. E, como j\u00e1 mostrado na postagem anterior, a localiza\u00e7\u00e3o do diret\u00f3rio de sa\u00edda, que por padr\u00e3o \u00e9 definido como build, pode ser redefinida atrav\u00e9s da vari\u00e1vel de ambiente OUTPUT_DIR. E como a localiza\u00e7\u00e3o da pasta de sa\u00edda varia de framework para framework, voc\u00ea simplesmente copia a sa\u00edda gerada para a pasta padr\u00e3o na imagem, ou seja, para \/opt\/apt-root\/output. Isso \u00e9 importante para entender a pr\u00f3xima parte deste artigo, mas agora vamos rapidamente revisar a pr\u00f3xima etapa \u2013 a fase de execu\u00e7\u00e3o.<\/p>\n<h4>Fase de execu\u00e7\u00e3o<\/h4>\n<p>\nEsta fase ocorre quando uma nova imagem, criada na fase de montagem, \u00e9 chamada usando docker run. Ela tamb\u00e9m acontece ao realizar a implanta\u00e7\u00e3o na plataforma OpenShift. Por padr\u00e3o <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/bucharest-gold\/centos7-s2i-web-app\/blob\/master\/s2i\/run\">script run<\/a><\/noindex> usa <noindex><a rel=\"nofollow\" href=\"https:\/\/www.npmjs.com\/package\/serve\">m\u00f3dulo serve<\/a><\/noindex> para servir conte\u00fado est\u00e1tico localizado no diret\u00f3rio de sa\u00edda padr\u00e3o mencionado acima.<\/p>\n<p>Esse m\u00e9todo \u00e9 bom para implanta\u00e7\u00f5es r\u00e1pidas de aplicativos, mas, na verdade, n\u00e3o \u00e9 recomendado servir conte\u00fado est\u00e1tico dessa forma. Como na verdade estamos servindo apenas conte\u00fado est\u00e1tico, o Node.js instalado dentro da nossa imagem n\u00e3o \u00e9 necess\u00e1rio \u2013 um servidor web \u00e9 suficiente.<\/p>\n<p>Ou seja, ao construir precisamos de uma coisa, ao executar \u2013 outra. Nessa situa\u00e7\u00e3o, constru\u00e7\u00f5es encadeadas ser\u00e3o \u00fateis.<\/p>\n<h3>Constru\u00e7\u00f5es encadeadas<\/h3>\n<p>\nVeja o que dizem sobre <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.okd.io\/latest\/dev_guide\/builds\/advanced_build_operations.html#dev-guide-chaining-builds\">constru\u00e7\u00f5es encadeadas<\/a><\/noindex> na documenta\u00e7\u00e3o do OpenShift:<\/p>\n<blockquote><p>\u00abDuas constru\u00e7\u00f5es podem ser vinculadas, onde uma gera a entidade compilada e a outra coloca essa entidade em uma imagem separada, que \u00e9 usada para executar essa entidade\u00bb.\n<\/p><\/blockquote>\n<p>\nEm outras palavras, podemos usar a imagem do Web App Builder para executar nossa constru\u00e7\u00e3o e, em seguida, usar a imagem do servidor web, como o NGINX, para servir nosso conte\u00fado.<\/p>\n<p>Assim, podemos usar a imagem do Web App Builder como um construtor \"limpo\" e ter uma imagem de runtime pequena.<\/p>\n<p>Agora vamos analisar isso com um exemplo espec\u00edfico.<\/p>\n<p>Para a pr\u00e1tica, usaremos <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/react-web-app\">um aplicativo React simples<\/a><\/noindex>, criado com a ferramenta de linha de comando create-react-app.<\/p>\n<p>Para juntar tudo, usaremos <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/react-web-app\/blob\/master\/.openshiftio\/application.yaml\">o arquivo de modelo do OpenShift<\/a><\/noindex>.<\/p>\n<p>Vamos analisar este arquivo em detalhes, come\u00e7ando pela se\u00e7\u00e3o de par\u00e2metros.<\/p>\n<pre><code class=\"plaintext\">parameters:\n  - name: SOURCE_REPOSITORY_URL\n    description: A URL de origem para o aplicativo\n    displayName: URL de Origem\n    required: true\n  - name: SOURCE_REPOSITORY_REF\n    description: O nome do branch para o aplicativo\n    displayName: Branch de Origem\n    value: master\n    required: true\n  - name: SOURCE_REPOSITORY_DIR\n    description: O local dentro do reposit\u00f3rio de origem do aplicativo\n    displayName: Diret\u00f3rio de Origem\n    value: .\n    required: true\n  - name: OUTPUT_DIR\n    description: O local dos arquivos est\u00e1ticos compilados do seu construtor de aplicativos web\n    displayName: Diret\u00f3rio de Sa\u00edda\n    value: build\n    required: false\n<\/code><\/pre>\n<p>\nAqui tudo \u00e9 bastante claro, mas vale a pena prestar aten\u00e7\u00e3o no par\u00e2metro OUTPUT_DIR. Para o aplicativo React do nosso exemplo, n\u00e3o h\u00e1 com o que se preocupar, pois o React usa como pasta de sa\u00edda o valor padr\u00e3o. No entanto, para aplica\u00e7\u00f5es Angular ou algo semelhante, este par\u00e2metro precisar\u00e1 ser alterado adequadamente.<\/p>\n<p>Agora vamos dar uma olhada na se\u00e7\u00e3o de 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>\nObserve as terceira e quarta imagens. Ambas est\u00e3o definidas como imagens Docker, e fica claro de onde elas v\u00eam.<\/p>\n<p>A terceira imagem \u00e9 o web-app-builder, e ela \u00e9 originada de nodeshift\/ubi8-s2i-web-app com a tag 10.x no <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/r\/nodeshift\/ubi8-s2i-web-app\/\">Docker hub<\/a><\/noindex>.<\/p>\n<p>A quarta imagem \u00e9 a imagem NGINX (vers\u00e3o 1.12) com a tag latest no <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/r\/centos\/nginx-112-centos7\/\">Docker hub<\/a><\/noindex>.<\/p>\n<p>Agora vamos olhar as duas primeiras imagens. Ambas est\u00e3o vazias no in\u00edcio e s\u00e3o criadas apenas na fase de constru\u00e7\u00e3o (build phase). A primeira imagem, react-web-app-builder, ser\u00e1 o resultado da fase de montagem, que combinar\u00e1 a imagem web-app-builder-runtime e nosso c\u00f3digo fonte. \u00c9 por isso que inclu\u00edmos no nome dessa imagem \"-builder\".<\/p>\n<p>A segunda imagem, react-web-app-runtime, ser\u00e1 o resultado da combina\u00e7\u00e3o de nginx-image-runtime e alguns arquivos da imagem react-web-app-builder. Esta imagem tamb\u00e9m ser\u00e1 utilizada durante o deploy e conter\u00e1 apenas o servidor web e o HTML, JavaScript e CSS est\u00e1tico do nosso aplicativo.<\/p>\n<p>Confuso? Vamos dar uma olhada nas configura\u00e7\u00f5es de constru\u00e7\u00e3o e ficar\u00e1 um pouco mais claro.<\/p>\n<p>No nosso template, h\u00e1 duas configura\u00e7\u00f5es de constru\u00e7\u00e3o. Aqui est\u00e1 a primeira delas, que \u00e9 bastante padr\u00e3o:<\/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>\nComo podemos ver, a linha com a etiqueta 1 nos diz que o resultado desta constru\u00e7\u00e3o ser\u00e1 colocado na imagem react-web-app-builder, que vimos anteriormente na se\u00e7\u00e3o de ImageStreams.<\/p>\n<p>A linha com a etiqueta 2 indica de onde pegar o c\u00f3digo. Neste caso, \u00e9 um reposit\u00f3rio git, e o local, ref e diret\u00f3rio de contexto s\u00e3o definidos pelas vari\u00e1veis que j\u00e1 vimos acima.<\/p>\n<p>A linha com a etiqueta 3 \u00e9 algo que j\u00e1 vimos na se\u00e7\u00e3o de par\u00e2metros. Ela adiciona a vari\u00e1vel de ambiente OUTPUT_DIR, que em nosso exemplo \u00e9 igual a build.<br \/>\nA linha com a etiqueta 4 indica que devemos usar a imagem web-app-builder-runtime, que j\u00e1 vimos na se\u00e7\u00e3o de ImageStreams.<\/p>\n<p>A linha com a etiqueta 5 diz que queremos usar a constru\u00e7\u00e3o incremental, se a imagem S2I a suportar, e a imagem Web App Builder \u2013 suporta. Na primeira execu\u00e7\u00e3o, ap\u00f3s a conclus\u00e3o da fase de montagem, a imagem salvar\u00e1 a pasta node_modules em um arquivo compactado. Ent\u00e3o, nas execu\u00e7\u00f5es seguintes, a imagem apenas descompactar\u00e1 essa pasta para reduzir a dura\u00e7\u00e3o da constru\u00e7\u00e3o.<\/p>\n<p>E, finalmente, a linha com a etiqueta 6 \u2013 s\u00e3o apenas alguns gatilhos para que a constru\u00e7\u00e3o seja iniciada automaticamente, sem interven\u00e7\u00e3o manual, quando algo muda.<\/p>\n<p>Em geral, esta \u00e9 uma configura\u00e7\u00e3o de constru\u00e7\u00e3o bastante padr\u00e3o.<\/p>\n<p>Agora, vamos olhar para a segunda configura\u00e7\u00e3o de constru\u00e7\u00e3o. Ela \u00e9 muito parecida com a primeira, mas h\u00e1 uma diferen\u00e7a 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\\\/.\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>\nEnt\u00e3o, a segunda configura\u00e7\u00e3o do build \u00e9 react-web-app-runtime, e ela come\u00e7a de maneira bastante padr\u00e3o.<\/p>\n<p>Na linha com o r\u00f3tulo 1, n\u00e3o h\u00e1 nada de novo \u2014 ela apenas indica que o resultado do build \u00e9 colocado na imagem react-web-app-runtime.<\/p>\n<p>A linha com o r\u00f3tulo 2, assim como na configura\u00e7\u00e3o anterior, indica de onde obter o c\u00f3digo-fonte. Mas note que aqui estamos dizendo que ele vem da imagem. E, especificamente, da imagem que acabamos de criar \u2014 a react-web-app-builder (indicada na linha com o r\u00f3tulo 3). Os arquivos que queremos usar est\u00e3o dentro da imagem, e sua localiza\u00e7\u00e3o \u00e9 definida na linha com o r\u00f3tulo 4, que neste caso \u00e9 \/opt\/app-root\/output\/. Se voc\u00ea se lembra, \u00e9 exatamente para l\u00e1 que s\u00e3o colocados os arquivos gerados como resultado da constru\u00e7\u00e3o do nosso aplicativo.<\/p>\n<p>A pasta de destino, especificada na linha com o r\u00f3tulo 5, \u00e9 simplesmente o diret\u00f3rio atual (todo esse processo, lembre-se, acontece dentro de uma coisa m\u00e1gica chamada OpenShift, e n\u00e3o em seu computador local).<\/p>\n<p>A se\u00e7\u00e3o strategy \u2014 a linha com o r\u00f3tulo 6 \u2014 tamb\u00e9m \u00e9 semelhante \u00e0 primeira configura\u00e7\u00e3o do build. Mas desta vez, vamos usar o nginx-image-runtime, que j\u00e1 vimos na se\u00e7\u00e3o ImageStream.<\/p>\n<p>Finalmente, a linha com o r\u00f3tulo 7 \u00e9 a se\u00e7\u00e3o de gatilhos que ativa esse build toda vez que a imagem react-web-app-builder \u00e9 alterada.<\/p>\n<p>No restante, este template cont\u00e9m uma configura\u00e7\u00e3o de implanta\u00e7\u00e3o bastante padr\u00e3o, al\u00e9m de coisas relacionadas a servi\u00e7os e rotas, mas n\u00e3o vamos nos aprofundar nisso. Observe que a imagem que ser\u00e1 implantada \u00e9 a imagem react-web-app-runtime.<\/p>\n<h3>Implanta\u00e7\u00e3o do aplicativo<\/h3>\n<p>\nEnt\u00e3o, depois de olharmos para o template, vejamos como us\u00e1-lo para implantar um aplicativo.<\/p>\n<p>Podemos usar a ferramenta de linha de comando OpenShift chamada oc, para implantar nosso 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>\nO primeiro comando na tela acima \u00e9 uma maneira intencionalmente t\u00e9cnica de encontrar o template \/openshiftio\/application.yaml.<\/p>\n<p>O segundo comando simplesmente cria um novo aplicativo com base nesse template.<\/p>\n<p>Depois que esses comandos forem executados, veremos que tivemos duas builds:<\/p>\n<p><img decoding=\"async\" alt=\"Aplica\u00e7\u00f5es modernas no OpenShift, parte 2: constru\u00e7\u00f5es encadeadas\" src=\"\/wp-content\/uploads\/2020\/08\/c6b2b2fcadfcd3e5a8a2adb4eff69bf2.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>E voltando \u00e0 tela de Vis\u00e3o Geral, veremos um pod em execu\u00e7\u00e3o:<\/p>\n<p><img decoding=\"async\" alt=\"Aplica\u00e7\u00f5es modernas no OpenShift, parte 2: constru\u00e7\u00f5es encadeadas\" src=\"\/wp-content\/uploads\/2020\/08\/983fab3029d222555dc13790d4a3e70f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Um clique no link nos levar\u00e1 ao nosso aplicativo, que se apresenta como a p\u00e1gina padr\u00e3o do React App:<\/p>\n<p><img decoding=\"async\" alt=\"Aplica\u00e7\u00f5es modernas no OpenShift, parte 2: constru\u00e7\u00f5es encadeadas\" src=\"\/wp-content\/uploads\/2020\/08\/d5b658875e0e865bf456955aaac15464.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<h3>Complemento 1<\/h3>\n<p>\nPara os f\u00e3s do Angular, tamb\u00e9m temos <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/angular-web-app\">exemplo de aplica\u00e7\u00e3o<\/a><\/noindex>.<\/p>\n<p>O padr\u00e3o aqui \u00e9 o mesmo, exceto pela vari\u00e1vel OUTPUT_DIR.<\/p>\n<h3>Complemento 2<\/h3>\n<p>\nNeste artigo, usamos o NGINX como servidor web, mas \u00e9 bastante f\u00e1cil substitu\u00ed-lo pelo Apache, basta alterar no arquivo de modelo <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/react-web-app\/blob\/master\/.openshiftio\/application.yaml#L66\">imagem do NGINX<\/a><\/noindex> para <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/r\/centos\/httpd-24-centos7\/\">imagem do Apache<\/a><\/noindex>.<\/p>\n<h3>Conclus\u00e3o<\/h3>\n<p>\nNa primeira parte desta s\u00e9rie, mostramos como implantar rapidamente aplica\u00e7\u00f5es web modernas na plataforma OpenShift. Hoje, exploramos o que faz a imagem da Web App e como ela pode ser combinada com um servidor web puro como o NGINX usando builds encadeados (chained builds) para organizar uma constru\u00e7\u00e3o mais adequada para condi\u00e7\u00f5es de produ\u00e7\u00e3o. No pr\u00f3ximo e \u00faltimo artigo desta s\u00e9rie, mostraremos como executar um servidor de desenvolvimento no OpenShift para sua aplica\u00e7\u00e3o e garantir a sincroniza\u00e7\u00e3o de arquivos locais e remotos.<\/p>\n<h3>Conte\u00fado desta s\u00e9rie de artigos<\/h3>\n<p><\/p>\n<ul>\n<li>Parte 1: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/redhatrussia\/blog\/511954\/\">como implantar aplica\u00e7\u00f5es web modernas em apenas alguns passos<\/a><\/noindex>;<\/li>\n<li>Parte 2: como aplicar a nova imagem S2I junto com uma imagem de servidor HTTP existente, como o NGINX, usando builds encadeados do OpenShift para organizar uma implanta\u00e7\u00e3o de produ\u00e7\u00e3o;<\/li>\n<li>Parte 3: como executar um servidor de desenvolvimento na plataforma OpenShift para sua aplica\u00e7\u00e3o e sincroniz\u00e1-lo com o sistema de arquivos local.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Recursos adicionais<\/h3>\n<p><\/p>\n<ul>\n<li>E-book gratuito <noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/books\/deploying-openshift\">Implantando no OpenShift<\/a><\/noindex>.<\/li>\n<li>Informa\u00e7\u00f5es sobre <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.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\/pt\/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=\"pt_PT\" \/>\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\/pt\/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\udd47 Aplica\u00e7\u00f5es modernas no OpenShift, parte 2: builds encadeados chained builds | ProHoster","description":"Ol\u00e1 a todos! Estamos de volta com o segundo post da nossa s\u00e9rie, onde mostramos como implantar aplica\u00e7\u00f5es web modernas no Red Hat OpenShift.","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-2-svyazannye-sborki-chained-builds","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","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\/pt\/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\/pt\/wp-json\/wp\/v2\/posts\/90874","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=90874"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/90874\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/90875"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=90874"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=90874"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=90874"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}