Aplicativos modernos no OpenShift, parte 2: compilações encadeadas

Olá a todos! Este é o segundo post de nossa série em que mostramos como implantar aplicações web modernas no Red Hat OpenShift.

Aplicativos modernos no OpenShift, parte 2: compilações encadeadas

Na postagem anterior, abordamos levemente os recursos da nova imagem do construtor S2I (source-to-image), que foi projetada para construir e implantar aplicativos da web modernos na plataforma OpenShift. Então estávamos interessados ​​​​no tópico de implantação rápida de um aplicativo e hoje veremos como usar uma imagem S2I como uma imagem de construtor “pura” e combiná-la com assemblies OpenShift relacionados.

Limpar imagem do construtor

Como mencionamos na Parte XNUMX, a maioria dos aplicativos web modernos possui um chamado estágio de construção, que normalmente executa operações como transpilação de código, concatenação de vários arquivos e minificação. Os arquivos obtidos como resultado dessas operações - e estes são HTML, JavaScript e CSS estáticos - são armazenados na pasta de saída. A localização desta pasta geralmente depende de quais ferramentas de construção estão sendo usadas, e para React esta será a pasta ./build (voltaremos a isso com mais detalhes abaixo).

Fonte para imagem (S2I)

Neste post não abordamos o tema “o que é S2I e como usá-lo” (você pode ler mais sobre isso aqui), mas é importante ter clareza sobre as duas etapas desse processo para entender o que uma imagem do Web App Builder faz.

Fase de montagem

A fase de montagem é de natureza muito semelhante ao que acontece quando você executa docker build e obtém uma nova imagem do Docker. Conseqüentemente, esta etapa ocorre ao iniciar uma construção na plataforma OpenShift.

No caso de uma imagem do Web App Builder, ele é responsável por instalar as dependências do seu aplicativo e executar o build. montar roteiro. Por padrão, a imagem do construtor usa a construção npm run build, mas isso pode ser substituído por meio da variável de ambiente NPM_BUILD.

Como dissemos anteriormente, a localização do aplicativo finalizado e já construído depende das ferramentas que você usa. Por exemplo, no caso do React esta será a pasta ./build, e para aplicações Angular será a pasta project_name/dist. E, como já mostrado no post anterior, a localização do diretório de saída, que está configurado para build por padrão, pode ser substituída através da variável de ambiente OUTPUT_DIR. Bem, como a localização da pasta de saída difere de framework para framework, basta copiar a saída gerada para a pasta padrão na imagem, ou seja, /opt/apt-root/output. Isso é importante para a compreensão do restante deste artigo, mas por enquanto vamos examinar rapidamente o próximo estágio – a fase de execução.

fase de execução

Este estágio ocorre quando uma chamada para docker run é feita na nova imagem criada durante o estágio de montagem. O mesmo acontece ao implantar na plataforma OpenShift. Padrão executar script usa módulo de atendimento para servir conteúdo estático localizado no diretório de saída padrão acima.

Esse método é bom para implantar aplicativos rapidamente, mas geralmente não é recomendado servir conteúdo estático dessa forma. Bem, como na realidade servimos apenas conteúdo estático, não precisamos do Node.js instalado dentro da nossa imagem - um servidor web será suficiente.

Ou seja, na hora de montar precisamos de uma coisa, na hora de executar precisamos de outra. Nessa situação, as compilações encadeadas são úteis.

Construções encadeadas

É sobre isso que eles escrevem construções encadeadas na documentação do OpenShift:

“Dois assemblies podem ser vinculados, 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 nossa construção e, em seguida, usar a imagem do servidor web, o mesmo NGINX, para servir nosso conteúdo.

Assim, podemos usar a imagem do Web App Builder como um construtor “puro” e ao mesmo tempo ter uma pequena imagem de tempo de execução.

Agora vamos ver isso com um exemplo específico.

Para treinamento usaremos aplicativo React simples, criado usando a ferramenta de linha de comando create-react-app.

Isso nos ajudará a juntar tudo Arquivo de modelo do OpenShift.

Vejamos esse arquivo com mais detalhes e comecemos 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 aqui é bem claro, mas vale a pena prestar atenção no parâmetro OUTPUT_DIR. Para o aplicativo React em nosso exemplo, não há com o que se preocupar, pois o React usa o valor padrão como pasta de saída, mas no caso do Angular ou qualquer 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. Ambos são definidos como imagens Docker e você pode ver claramente de onde vêm.

A terceira imagem é web-app-builder e vem de nodeshift/ubi8-s2i-web-app marcado como 10.x em Hub do Docker.

A quarta é uma imagem NGINX (versão 1.12) com a tag mais recente em Hub do Docker.

Agora vamos dar uma olhada nas duas primeiras imagens. Ambos estão vazios no início e são criados apenas durante a fase de construção. A primeira imagem, react-web-app-builder, será o resultado de uma etapa de montagem que combinará a imagem web-app-builder-runtime e nosso código-fonte. É por isso que adicionamos “-builder” ao nome desta imagem.

A segunda imagem - react-web-app-runtime - será o resultado da combinação de nginx-image-runtime e alguns arquivos da imagem react-web-app-builder. Esta imagem também será usada durante a implantação e conterá apenas o servidor web e HTML estático, JavaScript, CSS da nossa aplicação.

Confuso? Agora vamos dar uma olhada nas configurações de compilação e isso ficará um pouco mais claro.

Nosso modelo possui duas configurações de construção. 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 com o rótulo 1 diz que o resultado desta construção será colocado na mesma imagem react-web-app-builder que vimos um pouco antes na seção ImageStreams.

A linha rotulada 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 determinadas pelos parâmetros que já vimos acima.

A linha rotulada como 3 é o que já vimos na seção de parâmetros. Ele adiciona a variável de ambiente OUTPUT_DIR, que em nosso exemplo é build.
A linha rotulada como 4 diz para usar a imagem web-app-builder-runtime, que já vimos na seção ImageStream.

A linha rotulada 5 diz que queremos usar uma construção incremental se a imagem S2I suportar, e a imagem do Web App Builder suporta. Na primeira inicialização, após a conclusão da etapa de montagem, a imagem salvará a pasta node_modules em um arquivo compactado. Então, nas execuções subsequentes, a imagem simplesmente descompactará esta pasta para reduzir o tempo de construção.

E, finalmente, a linha rotulada como 6 são apenas alguns gatilhos para fazer a compilação ser executada automaticamente, sem intervenção manual, quando algo muda.

No geral, 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 rotulada como 1 não é novidade - ela simplesmente diz que o resultado da compilação é colocado na imagem react-web-app-runtime.

A linha rotulada como 2, como na configuração anterior, indica de onde obter o código-fonte. Mas observe que aqui estamos dizendo que é tirado da imagem. Além disso, a partir da imagem que acabamos de criar - do react-web-app-builder (indicado na linha 3). Os arquivos que queremos usar estão dentro da imagem e sua localização está definida na linha 4, no nosso caso é /opt/app-root/output/. Se você se lembra, é aqui que são armazenados os arquivos gerados com base nos resultados da construção de nosso aplicativo.

A pasta de destino especificada no termo com rótulo 5 é simplesmente o diretório atual (lembre-se, isso é tudo executado dentro de alguma coisa mágica chamada OpenShift, e 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 usaremos o nginx-image-runtime, que já vimos na seção ImageStream.

Finalmente, a linha rotulada como 7 é uma seção de gatilhos que ativarão esta compilação toda vez que a imagem do react-web-app-builder for alterada.

Caso contrário, este modelo contém configurações de implantação bastante padrão, bem como itens relacionados a serviços e rotas, mas não entraremos em muitos detalhes. Observe que a imagem que será implantada é a imagem react-web-app-runtime.

Implantação de aplicativos

Agora que vimos o modelo, vamos ver como usá-lo para implantar um aplicativo.

Podemos usar a 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 deliberadamente projetada de encontrar um template./openshiftio/application.yaml.

O segundo comando simplesmente cria um novo aplicativo baseado neste modelo.

Depois que esses comandos funcionarem, veremos que temos duas montagens:

Aplicativos modernos no OpenShift, parte 2: compilações encadeadas

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

Aplicativos modernos no OpenShift, parte 2: compilações encadeadas

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

Aplicativos modernos no OpenShift, parte 2: compilações encadeadas

Complemento 1

Para os amantes do Angular também temos exemplo de aplicação.

O padrão aqui é o mesmo, exceto pela variável OUTPUT_DIR.

Complemento 2

Neste artigo utilizamos o NGINX como servidor web, mas é bastante fácil substituí-lo pelo Apache, basta alterar o template no arquivo imagem NGINX em Imagem Apache.

Conclusão

Na primeira parte desta série, mostramos como implementar rapidamente aplicações web modernas na plataforma OpenShift. Hoje vimos o que uma imagem de aplicativo da Web faz e como ela pode ser combinada com um servidor da Web puro como o NGINX usando construções encadeadas para criar uma construção de aplicativo mais pronta para produção. No próximo e último artigo desta série, mostraremos como executar um servidor de desenvolvimento para sua aplicação no OpenShift e garantir a sincronização de arquivos locais e remotos.

Conteúdo desta série de artigos

  • Parte 1: como implantar aplicativos web modernos em apenas algumas etapas;
  • Parte 2: Como usar uma nova imagem S2I com uma imagem de servidor HTTP existente, como NGINX, usando assemblies OpenShift associados para implantação de produção;
  • Parte 3: como executar um servidor de desenvolvimento para sua aplicação na plataforma OpenShift e sincronizá-lo com o sistema de arquivos local.

Recursos adicionais

Fonte: habr.com

Adicionar um comentário