Applicazioni moderne su OpenShift, parte 2: build collegate chained builds

Ciao a tutti! Ecco il secondo post della nostra serie in cui mostriamo come distribuire applicazioni web moderne su Red Hat OpenShift.

Applicazioni moderne su OpenShift, parte 2: build collegate chained builds

Nel post precedente abbiamo accennato alle capacità della nuova immagine builder S2I (source-to-image), progettata per costruire e distribuire applicazioni web moderne sulla piattaforma OpenShift. In quella occasione ci siamo concentrati sulla rapida distribuzione dell'applicazione, mentre oggi vedremo come utilizzare l'immagine S2I come immagine builder 'pulita' e combinarla con build collegate di OpenShift.

Builder immagine pulita

Come abbiamo accennato nella prima parte, la maggior parte delle applicazioni web moderne ha una cosiddetta fase di assemblaggio, in cui vengono generalmente eseguite operazioni come la trascrizione del codice, la concatenazione di vari file e la minificazione. I file risultanti da queste operazioni – ovvero HTML statico, JavaScript e CSS – vengono collocati nella cartella output. La posizione di questa cartella dipende generalmente dagli strumenti di assemblaggio utilizzati, e per React sarà la cartella ./build (torneremo su questo argomento più avanti).

Source-to-Image (S2I)

In questo post non trattiamo affatto il tema di 'cos'è S2I e come utilizzarlo' (puoi leggere ulteriori dettagli qui), ma è importante avere chiara l'idea delle due fasi di questo processo per comprendere cosa fa l'immagine Web App Builder.

Fase di assemblaggio

La fase di assemblaggio è di fatto molto simile a ciò che accade quando esegui un docker build e ottieni una nuova immagine Docker. Pertanto, questa fase si verifica quando avvii il build sulla piattaforma OpenShift.

Nel caso dell'immagine Web App Builder, l'installazione delle dipendenze della tua applicazione e l'avvio del build sono gestiti dallo assemble script. Di default, l'immagine builder utilizza la struttura npm run build, ma può essere sovrascritta tramite la variabile d'ambiente NPM_BUILD.

Come accennato in precedenza, la posizione dell'applicazione già assemblata dipende dagli strumenti utilizzati. Ad esempio, nel caso di React sarà la cartella ./build, mentre per le applicazioni Angular sarà la cartella project_name/dist. E, come mostrato nel post precedente, la posizione della cartella output, impostata di default come build, può essere sovrascritta tramite la variabile d'ambiente OUTPUT_DIR. Poiché la posizione della cartella output varia a seconda del framework, è sufficiente copiare l'output generato nella cartella standard all'interno dell'immagine, precisamente in /opt/apt-root/output. Questo è importante per comprendere la parte successiva di questo articolo, ma per ora diamo un'occhiata rapida alla fase successiva – fase di esecuzione.

Fase di esecuzione

Questa fase si verifica quando viene eseguito un docker run per la nuova immagine creata nella fase di assemblaggio. Si verifica anche durante il deployment sulla piattaforma OpenShift. Di default, il script di esecuzione utilizza serve module gestisce i contenuti statici che si trovano nella suddetta cartella output standard.

Questo metodo è buono per la rapida distribuzione delle applicazioni, ma in realtà non è consigliabile gestire contenuti statici in questo modo. Poiché in effetti stiamo solo servendo contenuti statici, l'installazione di Node.js all'interno della nostra immagine non è necessaria: un semplice server web è sufficiente.

In altre parole, abbiamo bisogno di una cosa in fase di costruzione e di un'altra in fase di esecuzione. In questa situazione, le build collegate (chained builds) possono risultare utili.

Build collegate

Ecco cosa dice la documentazione di OpenShift riguardo alle chained builds :

"Due build possono essere collegate tra loro, in cui una genera un'entità compilata e l'altra colloca questa entità in un'immagine separata, utilizzata per eseguire questa entità."

In altre parole, possiamo utilizzare l'immagine Web App Builder per eseguire la nostra build, e quindi utilizzare l'immagine del server web, come NGINX, per gestire il nostro contenuto.

In questo modo, possiamo utilizzare l'immagine Web App Builder come builder 'pulita' e avere un'immagine runtime di dimensioni contenute.

Ora esaminiamo un esempio concreto.

Per fare pratica, utilizzeremo un semplice applicazione React, creata utilizzando il tool da riga di comando create-react-app.

Per unire tutto, il file template di OpenShift.

ci aiuterà. Analizziamo questo file più nel dettaglio, partendo dalla sezione dei parametri.

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

Qui tutto è abbastanza chiaro, ma è necessario prestare attenzione al parametro OUTPUT_DIR. Per l'applicazione React del nostro esempio non c'è nulla di cui preoccuparsi, poiché React utilizza come cartella di output il valore predefinito, ma nel caso di Angular o di qualcos'altro, questo parametro dovrà essere modificato di conseguenza.

Ora diamo un'occhiata alla sezione degli ImageStream.

- 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'

Guarda le terze e quarte immagini. Entrambe sono definite come immagini Docker ed è evidente da dove provengono.

La terza immagine è web-app-builder, e proviene da nodeshift/ubi8-s2i-web-app con il tag 10.x su Docker hub.

La quarta è l'immagine NGINX (versione 1.12) con il tag latest su Docker hub.

Ora diamo un'occhiata alle prime due immagini. Entrambe sono vuote all'inizio e vengono create solo nella fase di build. La prima immagine, react-web-app-builder, sarà il risultato della fase di assemblaggio, che unirà l'immagine web-app-builder-runtime e il nostro codice sorgente. È per questo che abbiamo aggiunto «-builder» nel nome di quest'immagine.

La seconda immagine, react-web-app-runtime, sarà il risultato della combinazione dell'immagine nginx-image-runtime e di alcuni file dall'immagine react-web-app-builder. Quest'immagine sarà utilizzata anche per il deployment e conterrà solo il server web e il codice statico HTML, JavaScript, CSS della nostra applicazione.

Complicato? Ora diamo un'occhiata alle configurazioni di build e diventerà un po' più chiaro.

Nel nostro template ci sono due configurazioni di build. Ecco la prima, che è piuttosto standard:

  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

Come vediamo, la riga contrassegnata con 1 indica che il risultato di questa build sarà inserito nell'immagine react-web-app-builder che abbiamo visto prima nella sezione degli ImageStream.

La riga contrassegnata con 2 indica da dove prendere il codice. Nel nostro caso, questo è un repository git, e la posizione, il ref e la cartella di contesto sono definiti da parametri che abbiamo già visto sopra.

La riga contrassegnata con 3 è quella che abbiamo già visto nella sezione dei parametri. Aggiunge la variabile d'ambiente OUTPUT_DIR, che nel nostro esempio è uguale a build.
La riga contrassegnata con 4 indica di utilizzare l'immagine web-app-builder-runtime che abbiamo già visto nella sezione degli ImageStream.

La riga contrassegnata con 5 indica che vogliamo utilizzare un build incrementale, se l'immagine S2I lo supporta, e l'immagine Web App Builder lo fa. Al primo avvio, dopo il completamento della fase di assemblaggio, l'immagine salverà la cartella node_modules in un file zip. Poi, nei successivi avvi, l'immagine semplicemente decomprimerà questa cartella per ridurre il tempo di build.

E infine, la riga contrassegnata con 6 è solo qualche trigger per avviare automaticamente la build, senza intervento manuale, quando qualcosa cambia.

In generale, questa è una configurazione di build piuttosto standard.

Ora diamo un'occhiata alla seconda configurazione di build. È molto simile alla prima, ma c'è una differenza 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

Quindi, la seconda configurazione di build è react-web-app-runtime, e inizia in modo piuttosto standard.

Nella riga contrassegnata con 1 non c'è nulla di nuovo: dice semplicemente che il risultato della build verrà inserito nell'immagine react-web-app-runtime.

La riga con l'etichetta 2, come nella configurazione precedente, indica da dove prelevare il codice sorgente. Ma attenzione, qui diciamo che proviene dall'immagine. Inoltre, dall'immagine che abbiamo appena creato - da react-web-app-builder (indicata nella riga con l'etichetta 3). I file che vogliamo utilizzare si trovano all'interno dell'immagine e la loro posizione è specificata nella riga con l'etichetta 4, nel nostro caso è /opt/app-root/output/. Se ricordate, proprio lì vengono salvati i file generati al termine della compilazione della nostra applicazione.

La cartella di destinazione, specificata nella riga con l'etichetta 5, è semplicemente la directory corrente (tutto ciò, ricordiamolo, si svolge all'interno di una sorta di magia chiamata OpenShift, e non sul vostro computer locale).

La sezione strategy - la riga con l'etichetta 6 - è simile alla prima configurazione di compilazione. Solo che questa volta abbiamo intenzione di utilizzare nginx-image-runtime, che abbiamo già visto nella sezione ImageStream.

Infine, la riga con l'etichetta 7 è la sezione dei trigger, che attivano questa compilazione ogni volta che l'immagine react-web-app-builder cambia.

A parte questo, questo modello contiene una configurazione di deployment piuttosto standard, oltre ad elementi relativi ai servizi e ai percorsi, ma non approfondiremo questo aspetto. Notate che l'immagine che verrà distribuita è l'immagine react-web-app-runtime.

Distribuzione dell'applicazione

Quindi, dopo aver esaminato il modello, vediamo come utilizzarlo per distribuire un'applicazione.

Possiamo utilizzare lo strumento client OpenShift chiamato oc, per distribuire il nostro modello:

$ 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

Il primo comando nello screenshot sopra è un modo ingegneristico per trovare il modello ./openshiftio/application.yaml.

Il secondo comando semplicemente crea una nuova applicazione basata su questo modello.

Dopo che questi comandi sono stati eseguiti, vedremo che sono state create due compilazioni:

Applicazioni moderne su OpenShift, parte 2: build collegate chained builds

E tornando alla schermata Overview, vedremo il pod avviato:

Applicazioni moderne su OpenShift, parte 2: build collegate chained builds

Un clic sul link ci porterà alla nostra applicazione, che è una pagina dell'applicazione React App per impostazione predefinita:

Applicazioni moderne su OpenShift, parte 2: build collegate chained builds

Supplemento 1

Per gli amanti di Angular abbiamo anche un esempio di applicazione.

Il modello è lo stesso, eccetto per la variabile OUTPUT_DIR.

Appendice 2

In questo articolo abbiamo usato NGINX come server web, ma è abbastanza facile sostituirlo con Apache, basta cambiare nel file modello immagine NGINX con immagine Apache.

Conclusione

Nella prima parte di questa serie abbiamo mostrato come distribuire rapidamente applicazioni web moderne sulla piattaforma OpenShift. Oggi abbiamo esaminato cosa fa l'immagine Web App e come può essere combinata con un server web come NGINX attraverso build collegate (chained build) per organizzare una compilazione più adatta alle condizioni di produzione. Nell'ultimo articolo di questa serie, mostreremo come eseguire un server di sviluppo per la nostra applicazione su OpenShift e mantenere la sincronizzazione tra i file locali e remoti.

Contenuto di questa serie di articoli

  • Parte 1: come distribuire applicazioni web moderne in pochi semplici passaggi;
  • Parte 2: come applicare la nuova immagine S2I insieme a un'immagine HTTP server esistente, come NGINX, usando build collegate di OpenShift per organizzare distribuzioni in produzione;
  • Parte 3: come avviare un server di sviluppo per la propria applicazione sulla piattaforma OpenShift e sincronizzarlo con il file system locale.

Risorse aggiuntive

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS 🔥 Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS | ProHoster