Aplicaciones modernas en OpenShift, parte 2: compilaciones encadenadas

¡Hola a todos! Esta es la segunda publicación de nuestra serie en la que mostramos cómo implementar aplicaciones web modernas en Red Hat OpenShift.

Aplicaciones modernas en OpenShift, parte 2: compilaciones encadenadas

En la publicación anterior, abordamos ligeramente las capacidades de la nueva imagen del generador S2I (fuente a imagen), que está diseñada para crear e implementar aplicaciones web modernas en la plataforma OpenShift. Luego nos interesó el tema de la implementación rápida de una aplicación, y hoy veremos cómo usar una imagen S2I como una imagen de constructor "pura" y combinarla con ensamblajes OpenShift relacionados.

Limpiar imagen del constructor

Como mencionamos en la Parte XNUMX, la mayoría de las aplicaciones web modernas tienen la llamada etapa de compilación, que normalmente realiza operaciones como la transpilación de código, la concatenación de múltiples archivos y la minificación. Los archivos obtenidos como resultado de estas operaciones, y estos son HTML estático, JavaScript y CSS, se almacenan en la carpeta de salida. La ubicación de esta carpeta generalmente depende de las herramientas de compilación que se estén utilizando y, para React, esta será la carpeta ./build (volveremos a esto con más detalle a continuación).

Fuente a imagen (S2I)

En este post no tocamos el tema “qué es S2I y cómo usarlo” (puedes leer más sobre esto aquí), pero es importante tener claros los dos pasos de este proceso para comprender qué hace una imagen de Web App Builder.

Fase de montaje

La fase de ensamblaje es de naturaleza muy similar a lo que sucede cuando ejecuta Docker Build y termina con una nueva imagen de Docker. En consecuencia, esta etapa ocurre al iniciar una compilación en la plataforma OpenShift.

En el caso de una imagen de Web App Builder, es responsable de instalar las dependencias de su aplicación y ejecutar la compilación. ensamblar guión. De forma predeterminada, la imagen del generador utiliza la construcción npm run build, pero esto se puede anular mediante la variable de entorno NPM_BUILD.

Como dijimos anteriormente, la ubicación de la aplicación terminada y ya creada depende de las herramientas que utilice. Por ejemplo, en el caso de React esta será la carpeta ./build, y para aplicaciones Angular será la carpeta project_name/dist. Y, como ya se mostró en la publicación anterior, la ubicación del directorio de salida, que está configurado para compilarse de forma predeterminada, se puede anular mediante la variable de entorno OUTPUT_DIR. Bueno, dado que la ubicación de la carpeta de salida difiere de un marco a otro, simplemente copie el resultado generado en la carpeta estándar en la imagen, es decir, /opt/apt-root/output. Esto es importante para comprender el resto de este artículo, pero por ahora veamos rápidamente la siguiente etapa: la fase de ejecución.

fase de ejecución

Esta etapa ocurre cuando se realiza una llamada a Docker Run en la nueva imagen creada durante la etapa de ensamblaje. Lo mismo sucede cuando se implementa en la plataforma OpenShift. Por defecto ejecutar guión usos módulo de servicio para servir contenido estático ubicado en el directorio de salida estándar anterior.

Este método es bueno para implementar aplicaciones rápidamente, pero generalmente no se recomienda entregar contenido estático de esta manera. Bueno, dado que en realidad solo ofrecemos contenido estático, no necesitamos Node.js instalado dentro de nuestra imagen; un servidor web será suficiente.

En otras palabras, al ensamblar necesitamos una cosa, al ejecutar necesitamos otra. En esta situación, las compilaciones encadenadas resultan útiles.

Construcciones encadenadas

Esto es sobre lo que escriben. construcciones encadenadas en la documentación de OpenShift:

"Se pueden vincular dos ensamblajes, uno genera una entidad compilada y el otro aloja esa entidad en una imagen separada que se utiliza para ejecutar esa entidad".

En otras palabras, podemos usar la imagen de Web App Builder para ejecutar nuestra compilación y luego usar la imagen del servidor web, el mismo NGINX, para servir nuestro contenido.

Por lo tanto, podemos usar la imagen de Web App Builder como un constructor "puro" y al mismo tiempo tener una imagen de tiempo de ejecución pequeña.

Ahora veamos esto con un ejemplo específico.

Para el entrenamiento usaremos aplicación de reacción sencilla, creado usando la herramienta de línea de comando create-react-app.

Nos ayudará a juntar todo. Archivo de plantilla de OpenShift.

Veamos este archivo con más detalle y comencemos con la 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

Todo aquí está bastante claro, pero vale la pena prestar atención al parámetro OUTPUT_DIR. Para la aplicación React en nuestro ejemplo, no hay nada de qué preocuparse, ya que React usa el valor predeterminado como carpeta de salida, pero en el caso de Angular o cualquier otra cosa, este parámetro deberá cambiarse según sea necesario.

Ahora echemos un vistazo a la 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'

Echa un vistazo a la tercera y cuarta imágenes. Ambas se definen como imágenes de Docker y se puede ver claramente de dónde provienen.

La tercera imagen es web-app-builder y proviene de nodeshift/ubi8-s2i-web-app etiquetada como 10.x en Centro acoplable.

La cuarta es una imagen NGINX (versión 1.12) con la última etiqueta en Centro acoplable.

Ahora veamos las dos primeras imágenes. Ambos están vacíos al principio y se crean sólo durante la fase de construcción. La primera imagen, reaccionar-web-app-builder, será el resultado de un paso de ensamblaje que combinará la imagen web-app-builder-runtime y nuestro código fuente. Por eso agregamos "-builder" al nombre de esta imagen.

La segunda imagen, reaccionar-web-app-runtime, será el resultado de combinar nginx-image-runtime y algunos archivos de la imagen de reaccionar-web-app-builder. Esta imagen también se utilizará durante la implementación y solo contendrá el servidor web y HTML estático, JavaScript, CSS de nuestra aplicación.

¿Confundido? Ahora echemos un vistazo a las configuraciones de compilación y quedará un poco más claro.

Nuestra plantilla tiene dos configuraciones de compilación. Aquí está el primero, y es 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 puede ver, la línea con la etiqueta 1 dice que el resultado de esta compilación se colocará en la misma imagen del generador de aplicaciones web de reacción que vimos un poco antes en la sección ImageStreams.

La línea etiquetada con 2 le indica de dónde obtener el código. En nuestro caso, este es un repositorio git, y la ubicación, la referencia y la carpeta de contexto están determinadas por los parámetros que ya vimos anteriormente.

La línea etiquetada con 3 es lo que ya vimos en la sección de parámetros. Agrega la variable de entorno OUTPUT_DIR, que en nuestro ejemplo es compilación.
La línea etiquetada con 4 dice que se use la imagen en tiempo de ejecución del generador de aplicaciones web, que ya vimos en la sección ImageStream.

La línea etiquetada como 5 dice que queremos usar una compilación incremental si la imagen S2I la admite y la imagen de Web App Builder sí. En el primer lanzamiento, una vez completada la etapa de ensamblaje, la imagen guardará la carpeta node_modules en un archivo comprimido. Luego, en ejecuciones posteriores, la imagen simplemente descomprimirá esta carpeta para reducir el tiempo de compilación.

Y finalmente, la línea etiquetada como 6 son solo algunos factores desencadenantes para que la compilación se ejecute automáticamente, sin intervención manual, cuando algo cambia.

En general, esta es una configuración de compilación bastante estándar.

Ahora echemos un vistazo a la segunda configuración de compilación. Es muy similar al primero, pero hay una diferencia 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

Entonces, la segunda configuración de compilación es reaccionar-web-app-runtime y comienza siendo bastante estándar.

La línea etiquetada como 1 no es nada nuevo; simplemente dice que el resultado de la compilación se coloca en la imagen de tiempo de ejecución de la aplicación web de reacción.

La línea etiquetada con 2, como en la configuración anterior, indica de dónde obtener el código fuente. Pero fíjate que aquí decimos que está sacado de la imagen. Además, de la imagen que acabamos de crear, de reaccionar-web-app-builder (indicada en la línea etiquetada con 3). Los archivos que queremos usar están dentro de la imagen y su ubicación allí se establece en la línea etiquetada 4, en nuestro caso es /opt/app-root/output/. Si recuerdas, aquí es donde se almacenan los archivos generados en función de los resultados de la construcción de nuestra aplicación.

La carpeta de destino especificada en el término con la etiqueta 5 es simplemente el directorio actual (recuerde que todo esto se ejecuta dentro de algo mágico llamado OpenShift, y no en su computadora local).

La sección de estrategia (línea etiquetada con 6) también es similar a la primera configuración de compilación. Sólo que esta vez vamos a utilizar nginx-image-runtime, que ya vimos en la sección ImageStream.

Finalmente, la línea etiquetada como 7 es una sección de activadores que activarán esta compilación cada vez que cambie la imagen del generador de aplicaciones web de reacción.

De lo contrario, esta plantilla contiene una configuración de implementación bastante estándar, así como cosas relacionadas con servicios y rutas, pero no entraremos en demasiados detalles. Tenga en cuenta que la imagen que se implementará es la imagen de tiempo de ejecución de la aplicación web de reacción.

Implementación de aplicaciones

Ahora que hemos visto la plantilla, veamos cómo usarla para implementar una aplicación.

Podemos usar la herramienta cliente OpenShift llamada oc para implementar nuestra plantilla:

$ 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

El primer comando en la captura de pantalla anterior es una forma de ingeniería deliberada de encontrar una plantilla./openshiftio/application.yaml.

El segundo comando simplemente crea una nueva aplicación basada en esta plantilla.

Después de que estos comandos funcionen, veremos que tenemos dos ensamblajes:

Aplicaciones modernas en OpenShift, parte 2: compilaciones encadenadas

Y volviendo a la pantalla Descripción general, veremos el pod iniciado:

Aplicaciones modernas en OpenShift, parte 2: compilaciones encadenadas

Haga clic en el enlace y accederemos a nuestra aplicación, que es la página predeterminada de la aplicación React:

Aplicaciones modernas en OpenShift, parte 2: compilaciones encadenadas

Complemento 1

Para los amantes de Angular también tenemos aplicación de ejemplo.

El patrón aquí es el mismo, excepto por la variable OUTPUT_DIR.

Complemento 2

En este artículo utilizamos NGINX como servidor web, pero es bastante fácil reemplazarlo con Apache, simplemente cambie la plantilla en el archivo. Imagen NGINX en imagen apache.

Conclusión

En la primera parte de esta serie, mostramos cómo implementar rápidamente aplicaciones web modernas en la plataforma OpenShift. Hoy analizamos lo que hace una imagen de aplicación web y cómo se puede combinar con un servidor web puro como NGINX usando compilaciones encadenadas para crear una compilación de aplicación más lista para producción. En el siguiente y último artículo de esta serie, mostraremos cómo ejecutar un servidor de desarrollo para su aplicación en OpenShift y garantizar la sincronización de archivos locales y remotos.

Contenido de esta serie de artículos.

  • Parte 1: cómo implementar aplicaciones web modernas en solo unos pocos pasos;
  • Parte 2: Cómo utilizar una nueva imagen S2I con una imagen de servidor HTTP existente, como NGINX, utilizando ensamblajes OpenShift asociados para la implementación de producción;
  • Parte 3: cómo ejecutar un servidor de desarrollo para su aplicación en la plataforma OpenShift y sincronizarlo con el sistema de archivos local.

Recursos adicionales

Fuente: habr.com

Añadir un comentario