Aplicacións modernas en OpenShift, parte 2: compilacións encadeadas

Ola a todos! Esta é a segunda publicación da nosa serie na que mostramos como implementar aplicacións web modernas en Red Hat OpenShift.

Aplicacións modernas en OpenShift, parte 2: compilacións encadeadas

Na publicación anterior, tocamos lixeiramente as capacidades da nova imaxe do creador S2I (de orixe a imaxe), que está deseñada para construír e implantar aplicacións web modernas na plataforma OpenShift. Entón interesounos o tema da implantación rápida dunha aplicación, e hoxe veremos como usar unha imaxe S2I como imaxe de constructor "pura" e combinala con conxuntos OpenShift relacionados.

Imaxe limpa do constructor

Como mencionamos na parte XNUMX, a maioría das aplicacións web modernas teñen unha fase de compilación, que normalmente realiza operacións como a transpilación de código, a concatenación de ficheiros múltiples e a minificación. Os ficheiros obtidos como resultado destas operacións -e isto é HTML estático, JavaScript e CSS- gárdanse no cartafol de saída. A localización deste cartafol adoita depender das ferramentas de compilación que se utilicen e, para React, este será o cartafol ./build (volveremos sobre isto con máis detalle a continuación).

Fonte a imaxe (S2I)

Neste post non abordamos o tema "que é S2I e como usalo" (podes ler máis sobre isto aquí), pero é importante ter claro os dous pasos deste proceso para comprender o que fai unha imaxe de Web App Builder.

Fase de montaxe

A fase de montaxe é moi semellante ao que ocorre cando executas a compilación de Docker e acabas cunha nova imaxe de Docker. En consecuencia, esta etapa ocorre cando se inicia unha compilación na plataforma OpenShift.

No caso dunha imaxe de Web App Builder, é responsable de instalar as dependencias da súa aplicación e executar a compilación. montar guión. De forma predeterminada, a imaxe do constructor usa a construción npm run build, pero esta pódese substituír mediante a variable de ambiente NPM_BUILD.

Como dixemos anteriormente, a localización da aplicación rematada e xa construída depende das ferramentas que use. Por exemplo, no caso de React este será o cartafol ./build, e para as aplicacións Angular será o cartafol nome_proxecto/dist. E, como xa se mostrou na publicación anterior, a localización do directorio de saída, que está configurado para construír por defecto, pódese substituír a través da variable de ambiente OUTPUT_DIR. Ben, xa que a localización do cartafol de saída difire de marco a marco, simplemente copia a saída xerada no cartafol estándar da imaxe, é dicir, /opt/apt-root/output. Isto é importante para comprender o resto deste artigo, pero por agora vexamos rapidamente a seguinte fase: a fase de execución.

fase de execución

Esta fase prodúcese cando se fai unha chamada á execución do docker na nova imaxe creada durante a fase de montaxe. O mesmo ocorre cando se implementa na plataforma OpenShift. Por defecto executar script usos módulo de servizo para servir contido estático situado no directorio de saída estándar anterior.

Este método é bo para implementar rapidamente aplicacións, pero xeralmente non se recomenda servir contido estático deste xeito. Ben, dado que en realidade só servimos contido estático, non necesitamos Node.js instalado dentro da nosa imaxe; un servidor web será suficiente.

Noutras palabras, ao montar necesitamos unha cousa, ao executar necesitamos outra. Nesta situación, as construcións encadeadas son útiles.

Construcións encadeadas

Isto é o que escriben construcións encadeadas na documentación de OpenShift:

"Pódense enlazar dous conxuntos, un xerando unha entidade compilada e o outro hospedando esa entidade nunha imaxe separada que se usa para executar esa entidade".

Noutras palabras, podemos usar a imaxe do Web App Builder para executar a nosa compilación e, a continuación, usar a imaxe do servidor web, a mesma NGINX, para servir o noso contido.

Así, podemos usar a imaxe do Web App Builder como un constructor "puro" e ao mesmo tempo ter unha pequena imaxe de execución.

Agora vexamos isto cun exemplo específico.

Para adestramento utilizaremos aplicación sinxela React, creado usando a ferramenta de liña de comandos create-react-app.

Axudaranos a xuntar todo Ficheiro modelo OpenShift.

Vexamos este ficheiro con máis detalle e comecemos pola sección 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

Aquí está todo bastante claro, pero paga a pena prestar atención ao parámetro OUTPUT_DIR. Para a aplicación React do noso exemplo, non hai nada de que preocuparse, xa que React usa o valor predeterminado como cartafol de saída, pero no caso de Angular ou outra cousa, este parámetro terá que ser modificado segundo sexa necesario.

Agora imos dar unha ollada á sección 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'

Bótalle un ollo ás imaxes terceira e cuarta. Ambas están definidas como imaxes de Docker e podes ver claramente de onde veñen.

A terceira imaxe é web-app-builder e provén de nodeshift/ubi8-s2i-web-app etiquetada 10.x en Hub Docker.

A cuarta é unha imaxe de NGINX (versión 1.12) coa última etiqueta activada Hub Docker.

Agora vexamos as dúas primeiras imaxes. Ambos están baleiros ao inicio e créanse só durante a fase de compilación. A primeira imaxe, react-web-app-builder, será o resultado dun paso de montaxe que combinará a imaxe web-app-builder-runtime e o noso código fonte. É por iso que engadimos "-builder" ao nome desta imaxe.

A segunda imaxe - react-web-app-runtime - será o resultado da combinación de nginx-image-runtime e algúns ficheiros da imaxe react-web-app-builder. Esta imaxe tamén se utilizará durante a implantación e só conterá o servidor web e HTML estático, JavaScript, CSS da nosa aplicación.

Confundido? Agora vexamos as configuracións de compilación e quedará un pouco máis claro.

O noso modelo ten dúas configuracións de compilación. Aquí está o primeiro, e é bastante estándar:

  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 podes ver, a liña coa etiqueta 1 di que o resultado desta compilación colocarase na mesma imaxe react-web-app-builder que vimos un pouco antes na sección ImageStreams.

A liña etiquetada como 2 indica de onde obter o código. No noso caso, este é un repositorio git, e a localización, a referencia e o cartafol de contexto están determinados polos parámetros que xa vimos anteriormente.

A liña etiquetada como 3 é o que xa vimos na sección de parámetros. Engade a variable de ambiente OUTPUT_DIR, que no noso exemplo é compilar.
A liña etiquetada 4 di que se usa a imaxe web-app-builder-runtime, que xa vimos na sección ImageStream.

A liña etiquetada 5 di que queremos usar unha compilación incremental se a imaxe S2I o admite, e a imaxe do Web App Builder. No primeiro lanzamento, despois de que se complete a fase de montaxe, a imaxe gardará o cartafol node_modules nun ficheiro de arquivo. Despois, nas seguintes execucións, a imaxe simplemente descomprimirá este cartafol para reducir o tempo de construción.

E, finalmente, a liña etiquetada como 6 son só algúns disparadores para facer que a compilación se execute automaticamente, sen intervención manual, cando algo cambia.

En xeral, esta é unha configuración de compilación bastante estándar.

Agora vexamos a segunda configuración de compilación. É moi semellante ao primeiro, pero hai unha diferenza 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

Entón, a segunda configuración de compilación é react-web-app-runtime, e comeza bastante estándar.

A liña etiquetada como 1 non é nada novo: simplemente di que o resultado da compilación se coloca na imaxe react-web-app-runtime.

A liña etiquetada como 2, como na configuración anterior, indica de onde obter o código fonte. Pero fíxate que aquí estamos dicindo que está sacado da imaxe. Ademais, a partir da imaxe que acabamos de crear - de react-web-app-builder (indicado na liña etiquetada 3). Os ficheiros que queremos utilizar están dentro da imaxe e a súa localización alí está definida na liña etiquetada como 4, no noso caso é /opt/app-root/output/. Se o recordas, é onde se almacenan os ficheiros xerados en función dos resultados da construción da nosa aplicación.

O cartafol de destino especificado no termo coa etiqueta 5 é simplemente o directorio actual (este é todo, lembre, funcionando dentro dalgún cousa máxica chamada OpenShift, e non no seu ordenador local).

A sección de estratexia (liña etiquetada como 6) tamén é semellante á configuración da primeira compilación. Só que esta vez imos usar nginx-image-runtime, que xa vimos na sección ImageStream.

Finalmente, a liña etiquetada como 7 é unha sección de disparadores que activará esta compilación cada vez que cambie a imaxe react-web-app-builder.

En caso contrario, este modelo contén unha configuración de despregamento bastante estándar, así como cousas relacionadas con servizos e rutas, pero non imos entrar en demasiados detalles. Teña en conta que a imaxe que se despregará é a imaxe react-web-app-runtime.

Implantación de aplicacións

Entón, agora que botamos unha ollada ao modelo, vexamos como usalo para implementar unha aplicación.

Podemos usar a ferramenta cliente OpenShift chamada oc para implementar o noso 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 da captura de pantalla anterior é unha forma deliberada de enxeñería de atopar un modelo./openshiftio/application.yaml.

O segundo comando simplemente crea unha nova aplicación baseada neste modelo.

Despois de traballar estes comandos, veremos que temos dous conxuntos:

Aplicacións modernas en OpenShift, parte 2: compilacións encadeadas

E volvendo á pantalla Visión xeral, veremos o pod lanzado:

Aplicacións modernas en OpenShift, parte 2: compilacións encadeadas

Fai clic na ligazón e dirixirémonos á nosa aplicación, que é a páxina predeterminada da aplicación React:

Aplicacións modernas en OpenShift, parte 2: compilacións encadeadas

Suplemento 1

Para os amantes de Angular tamén temos aplicación de exemplo.

O patrón aquí é o mesmo, excepto a variable OUTPUT_DIR.

Suplemento 2

Neste artigo usamos NGINX como servidor web, pero é bastante sinxelo substituílo por Apache, basta con cambiar o modelo no ficheiro Imaxe NGINX en Imaxe Apache.

Conclusión

Na primeira parte desta serie, mostramos como implementar rapidamente aplicacións web modernas na plataforma OpenShift. Hoxe analizamos o que fai unha imaxe de aplicación web e como se pode combinar cun servidor web puro como NGINX usando compilacións encadeadas para crear unha compilación de aplicacións máis preparada para a produción. No seguinte e último artigo desta serie, mostraremos como executar un servidor de desenvolvemento para a súa aplicación en OpenShift e garantir a sincronización dos ficheiros locais e remotos.

Contidos desta serie de artigos

  • Parte de 1: como implementar aplicacións web modernas en poucos pasos;
  • Parte 2: Como usar unha nova imaxe S2I cunha imaxe de servidor HTTP existente, como NGINX, usando conxuntos OpenShift asociados para a implantación de produción;
  • Parte 3: como executar un servidor de desenvolvemento para a súa aplicación na plataforma OpenShift e sincronizalo co sistema de ficheiros local.

Recursos adicionais

Fonte: www.habr.com

Engadir un comentario