
No post anterior, falamos um pouco sobre os recursos da nova imagem do construtor S2I (source-to-image), que é projetada para construir e implantar aplicativos da web modernos na plataforma OpenShift. Então estávamos interessados no tópico de implementação rápida de aplicativos, mas hoje veremos como usar uma imagem S2I como uma imagem de construtor "limpa" e combiná-la com assemblies OpenShift relacionados.
Imagem limpa do construtor
Como mencionamos na primeira parte, a maioria dos aplicativos da web modernos tem um chamado estágio de construção, que geralmente executa operações como transpilação de código, concatenação de vários arquivos e minificação. Os arquivos resultantes - HTML estático, JavaScript e CSS - são adicionados à pasta de saída. A localização desta pasta geralmente depende de quais ferramentas de construção são usadas, e para React será a pasta ./build (voltaremos a isso com mais detalhes abaixo).
Source-to-Image (S2I)
Este post não é realmente sobre o que é S2I e como usá-lo (você pode ler mais sobre isso aqui ), mas é importante deixar claro sobre as duas etapas neste processo para entender o que a imagem do Web App Builder faz.
Fase de montagem
A etapa de montagem é inerentemente muito semelhante ao que acontece quando você executa o docker build e acaba com uma nova imagem do Docker. Da mesma forma, este estágio ocorre ao iniciar uma construção na plataforma OpenShift.
No caso de uma imagem do Web App Builder, o script assemble é responsável por instalar as dependências do seu aplicativo e executar o build . Por padrão, a imagem do construtor usa a construção npm run build, mas pode ser substituída por meio da variável de ambiente NPM_BUILD.
Como dissemos antes, a localização do aplicativo acabado e já construído depende de quais ferramentas você usa. Por exemplo, no caso do React, esta será a pasta. / Build, e para aplicativos Angular, a pasta project_name / dist. E, como mostrado na última postagem, a localização do diretório de saída, que é definido para construir por padrão, pode ser substituída por meio da variável de ambiente OUTPUT_DIR. Bem, como a localização da pasta de saída difere de estrutura para estrutura, você simplesmente copia a saída gerada para a pasta padrão na imagem, ou seja, / opt / apt-root / output. Isso é importante para entender o restante deste artigo, mas por enquanto vamos dar uma olhada rápida no próximo estágio - a execução (fase de execução).
Fase de execução
Este estágio ocorre quando a docker run é chamada em uma nova imagem criada durante o estágio de montagem. Isso também acontece durante a implantação na plataforma OpenShift. Por padrão, o script de execução usa o módulo serve para servir conteúdo estático localizado no diretório de saída padrão acima.
Este método é bom para implantar aplicativos rapidamente, mas geralmente não é recomendado servir conteúdo estático dessa forma. Bem, uma vez que servimos apenas conteúdo estático, o Node.js instalado dentro de nossa imagem não é necessário - um servidor web é suficiente.
Em outras palavras, precisamos de uma coisa durante a montagem e outra durante a execução. É aqui que as compilações encadeadas são úteis.
Construções encadeadas
Aqui está o que eles escrevem sobre compilações encadeadas na documentação do OpenShift:
"Dois assemblies podem ser vinculados um ao outro, com um gerando uma entidade compilada e o outro hospedando essa entidade em uma imagem separada que é usada para executar essa entidade."
Em outras palavras, podemos usar a imagem do Web App Builder para executar nosso build e, em seguida, usar a imagem do servidor da Web, NGINX, para servir nosso conteúdo.
Portanto, podemos usar a imagem do Web App Builder como um construtor puro e ainda ter uma pequena imagem de tempo de execução.
Agora vamos ver isso com um exemplo específico.
Para este tutorial, usaremos um aplicativo React simples construído com a ferramenta de linha de comando create-react-app.
O arquivo de modelo OpenShift nos ajudará a colocar tudo junto .
Vamos dar uma olhada neste arquivo e começar com a seção de parâmetros.
parameters:
- name: SOURCE_REPOSITORY_URL
description: The source URL for the application
displayName: Source URL
required: true
- name: SOURCE_REPOSITORY_REF
description: The branch name for the application
displayName: Source Branch
value: master
required: true
- name: SOURCE_REPOSITORY_DIR
description: The location within the source repo of the application
displayName: Source Directory
value: .
required: true
- name: OUTPUT_DIR
description: The location of the compiled static files from your web apps builder
displayName: Output Directory
value: build
required: false
Tudo está bem claro aqui, mas você deve prestar atenção ao parâmetro OUTPUT_DIR. Para o aplicativo React do nosso exemplo, não há nada com que se preocupar, já que o React usa o valor padrão como pasta de saída, mas no caso do Angular ou outro, esse parâmetro precisará ser alterado conforme necessário.
Agora vamos dar uma olhada na seção ImageStreams.
- apiVersion: v1
kind: ImageStream
metadata:
name: react-web-app-builder // 1
spec: {}
- apiVersion: v1
kind: ImageStream
metadata:
name: react-web-app-runtime // 2
spec: {}
- apiVersion: v1
kind: ImageStream
metadata:
name: web-app-builder-runtime // 3
spec:
tags:
- name: latest
from:
kind: DockerImage
name: nodeshift/ubi8-s2i-web-app:10.x
- apiVersion: v1
kind: ImageStream
metadata:
name: nginx-image-runtime // 4
spec:
tags:
- name: latest
from:
kind: DockerImage
name: 'centos/nginx-112-centos7:latest'
Dê uma olhada na terceira e quarta imagens. Ambas são definidas como imagens Docker e você pode ver claramente de onde elas vêm.
A terceira imagem é web-app-builder e vem de nodeshift / ubi8-s2i-web-app com tag 10.x no hub Docker .
A quarta é uma imagem NGINX (versão 1.12) com a tag mais recente no hub Docker .
Agora vamos dar uma olhada nas duas primeiras imagens. Ambos estão vazios no início e são criados apenas na fase de construção. A primeira imagem, react-web-app-builder, será o resultado de uma etapa de montagem que irá mesclar a imagem web-app-builder-runtime e nosso código-fonte. É por isso que colocamos "-builder" no nome desta imagem.
A segunda imagem - react-web-app-runtime - será o resultado da combinação do nginx-image-runtime e alguns arquivos da imagem react-web-app-builder. Essa imagem também será usada durante a implantação e conterá apenas o servidor da web e o HTML estático, JavaScript, CSS de nosso aplicativo.
Confuso? Agora vamos dar uma olhada nas configurações de construção e isso ficará um pouco mais claro.
Existem duas configurações de construção em nosso modelo. Aqui está o primeiro, e é bastante padrão:
apiVersion: v1
kind: BuildConfig
metadata:
name: react-web-app-builder
spec:
output:
to:
kind: ImageStreamTag
name: react-web-app-builder:latest // 1
source: // 2
git:
uri: ${SOURCE_REPOSITORY_URL}
ref: ${SOURCE_REPOSITORY_REF}
contextDir: ${SOURCE_REPOSITORY_DIR}
type: Git
strategy:
sourceStrategy:
env:
- name: OUTPUT_DIR // 3
value: ${OUTPUT_DIR}
from:
kind: ImageStreamTag
name: web-app-builder-runtime:latest // 4
incremental: true // 5
type: Source
triggers: // 6
- github:
secret: ${GITHUB_WEBHOOK_SECRET}
type: GitHub
- type: ConfigChange
- imageChange: {}
type: ImageChange
Como você pode ver, a linha identificada como 1 diz que o resultado dessa construção será colocado na mesma imagem react-web-app-builder que vimos anteriormente na seção ImageStreams.
A linha identificada como 2 informa de onde obter o código. No nosso caso, este é um repositório git, e a localização, ref e pasta de contexto são definidos pelos parâmetros que já vimos acima.
A linha identificada como 3 já é vista na seção de parâmetros. Ele adiciona a variável de ambiente OUTPUT_DIR, que é construída em nosso exemplo.
A linha identificada como 4 diz para usar a imagem web-app-builder-runtime que já vimos na seção ImageStream.
A linha rotulada como 5 diz que queremos usar uma construção incremental se a imagem S2I suportar e a imagem do Web App Builder sim. Na primeira inicialização, após concluir o estágio de montagem, a imagem salvará a pasta node_modules em um arquivo. Em seguida, nas execuções subsequentes, a imagem simplesmente descompactará essa pasta para reduzir o tempo de construção.
E, finalmente, a linha rotulada 6 é apenas alguns gatilhos para que o build seja iniciado automaticamente, sem intervenção manual, quando algo muda.
Em suma, esta é uma configuração de construção bastante padrão.
Agora vamos dar uma olhada na segunda configuração de compilação. É muito semelhante ao primeiro, mas há uma diferença importante.
apiVersion: v1
kind: BuildConfig
metadata:
name: react-web-app-runtime
spec:
output:
to:
kind: ImageStreamTag
name: react-web-app-runtime:latest // 1
source: // 2
type: Image
images:
- from:
kind: ImageStreamTag
name: react-web-app-builder:latest // 3
paths:
- sourcePath: /opt/app-root/output/. // 4
destinationDir: . // 5
strategy: // 6
sourceStrategy:
from:
kind: ImageStreamTag
name: nginx-image-runtime:latest
incremental: true
type: Source
triggers:
- github:
secret: ${GITHUB_WEBHOOK_SECRET}
type: GitHub
- type: ConfigChange
- type: ImageChange
imageChange: {}
- type: ImageChange
imageChange:
from:
kind: ImageStreamTag
name: react-web-app-builder:latest // 7
Portanto, a segunda configuração de compilação é react-web-app-runtime e começa bem padrão.
A linha identificada como 1 não é nova - apenas diz que o resultado da compilação está sendo colocado na imagem react-web-app-runtime.
A linha identificada como 2, como na configuração anterior, indica de onde obter o código-fonte. Mas observe que aqui dizemos que é tirado da imagem. Além disso, a partir da imagem que acabamos de criar - do react-web-app-builder (indicado na linha rotulada 3). Os arquivos que queremos usar estão localizados dentro da imagem e sua localização é especificada na linha rotulada 4, no nosso caso é / opt / app-root / output /. Se você se lembra, é aqui que os arquivos gerados a partir dos resultados da construção de nosso aplicativo são colocados.
A pasta de destino especificada na linha rotulada 5 é apenas o diretório atual (lembre-se, tudo isso está girando dentro de alguma coisa mágica chamada OpenShift, não no seu computador local).
A seção de estratégia - linha rotulada 6 - também é semelhante à primeira configuração de construção. Só que desta vez vamos usar o nginx-image-runtime, que já vimos na seção ImageStream.
Finalmente, a linha rotulada como 7 é a seção de gatilhos que dispara esta compilação toda vez que a imagem react-web-app-builder muda.
Caso contrário, este modelo contém uma configuração de implantação razoavelmente padrão, bem como coisas relacionadas a serviços e rotas, mas não entraremos nisso. Observe que a imagem que será implantada é a imagem react-web-app-runtime.
Implantar o aplicativo
Então, depois de dar uma olhada no modelo, vamos ver como usá-lo para implantar o aplicativo.
Podemos usar uma ferramenta cliente OpenShift chamada oc para implantar nosso modelo:
$ find . | grep openshiftio | grep application | xargs -n 1 oc apply -f
$ oc new-app --template react-web-app -p SOURCE_REPOSITORY_URL=https://github.com/lholmquist/react-web-app
O primeiro comando na captura de tela acima é uma maneira deliberada de engenharia para encontrar o modelo. / Openshiftio / application.yaml.
O segundo comando simplesmente cria um novo aplicativo com base neste modelo.
Depois que esses comandos forem executados, veremos que temos dois assemblies:

E, voltando à tela Visão geral, veremos o pod lançado:

Clique no link e seremos direcionados ao nosso aplicativo, que é a página padrão do React App:

Apêndice 1
Para os amantes do Angular, também temos um aplicativo de amostra .
O modelo é o mesmo aqui, exceto para a variável OUTPUT_DIR.
Apêndice 2
Neste artigo, utilizamos como servidor web o NGINX, mas é bastante fácil substituí-lo pelo Apache, basta trocar o arquivo template da imagem NGINX no caminho do Apache .
Conclusão
Na primeira parte desta série, mostramos como implantar rapidamente aplicativos da web modernos na plataforma OpenShift. Hoje vimos o que torna uma imagem de aplicativo da Web e como ela pode ser combinada com um servidor da Web puro como o NGINX usando compilações encadeadas para criar uma compilação de aplicativo mais pronta para produção. No próximo artigo final desta série, mostraremos como executar um servidor de desenvolvimento para seu aplicativo no OpenShift e manter os arquivos locais e remotos sincronizados.
Conteúdo desta série de artigos
- Parte 1: como implantar aplicativos da web modernos em apenas algumas etapas ;
- Parte 2: como usar uma nova imagem S2I junto com uma imagem de servidor HTTP existente, por exemplo, NGINX, usando assemblies OpenShift associados para organizar uma implantação de produção;
- 3: OpenShift .