(Italiano) GitHub Actions: Build e Push di Immagini Container con Quarkus CLI

GitHub Actions: Build e Push di Immagini Container con Quarkus CLI
GitHub Actions: Build e Push di Immagini Container con Quarkus CLI

Sorry, this entry is only available in Italiano.

Questo articolo nasce come compendio dell'articolo Quarkus: guida avanzata per il deploy su OpenShift pubblicato su Codemotion Magazine. Qui approfondiamo l'automazione della build e distribuzione di immagini native con GitHub Actions e Quarkus CLI, fornendo una guida pratica all'implementazione di una pipeline CI/CD efficace.

L'automazione del processo di build e distribuzione di immagini native rappresenta un elemento chiave nell'ottimizzazione del ciclo di sviluppo e rilascio di applicazioni. Questo articolo analizza come GitHub Actions possa essere sfruttato per orchestrare la build e la pubblicazione di immagini native di applicazioni Quarkus, utilizzando Quarkus CLI.

Il workflow descritto è implementato nel progetto quarkus-graphql-quickstart e si occupa di generare un'immagine nativa e distribuirla su un container registry. L'obiettivo principale è garantire efficienza, riproducibilità e scalabilità, minimizando l'intervento manuale nel processo di deployment.

Configurazione della GitHub Action

Il workflow è definito nel file docker_publish_native_quarkus_cli.yml. Di seguito, ne analizziamo le componenti principali, esplorando ogni aspetto in dettaglio.

Nella nostra GitHub Action, utilizziamo Quarkus CLI al posto di Maven per diversi motivi. Quarkus CLI offre un approccio più astratto rispetto a Maven, specialmente quando si lavora con diversi strumenti di build. Ecco alcuni motivi per preferire Quarkus CLI a Maven nelle pipeline:

  • Astrazione dello strumento di build: Quarkus CLI permette di interagire con progetti sia Maven che Gradle allo stesso modo. Questo significa che i comandi rimangono consistenti indipendentemente dal sistema di build sottostante.
  • Gestione semplificata delle estensioni: Quarkus CLI fornisce comandi intuitivi per trovare, aggiungere e rimuovere estensioni Quarkus, semplificando la gestione delle dipendenze del progetto.
  • Coerenza: L'uso di Quarkus CLI garantisce una maggiore coerenza tra i diversi progetti, specialmente in ambienti dove sia Maven che Gradle sono utilizzati.

In sintesi, l'uso di Quarkus CLI può semplificare e uniformare le operazioni di build, rendendo le pipeline più manutenibili e meno dipendenti dallo strumento di build specifico del progetto.

Eventi Trigger

Gli eventi trigger determinano quando la pipeline viene eseguita automaticamente. In questo caso, la pipeline si attiva nei seguenti scenari:

on:
  push:
    branches:
      - develop
      - main
  release:
    types: [ published ]
YAML

  • Push su develop e main: ogni volta che viene effettuato un push su queste branch, il workflow viene avviato per garantire che le ultime modifiche siano costruite e pubblicate immediatamente. Questo aiuta a mantenere aggiornate le immagini e a testare il codice più recente.
  • Pubblicazione di una release: quando viene pubblicata una nuova release, la pipeline si avvia automaticamente per costruire e distribuire un'immagine nativa basata sul codice stabile della release. Questo garantisce che le versioni ufficiali dell'applicazione siano immediatamente disponibili per l'uso in produzione.

Configurazione dei Job

La configurazione dei job definisce l'ambiente e la strategia di esecuzione della pipeline. In questo caso, il workflow utilizza una matrice di esecuzione per garantire compatibilità su diverse piattaforme e architetture.

jobs:
  docker:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ 'ubuntu-24.04', 'ubuntu-24.04-arm' ]
        include:
          - os: ubuntu-24.04
            current_platform: 'amd64'
          - os: ubuntu-24.04-arm
            current_platform: 'arm64'
YAML

Ogni job viene eseguito su uno dei due ambienti definiti nella matrice: Ubuntu 24.04 per AMD64 e Ubuntu 24.04 per ARM64. La strategia della matrice permette di eseguire il workflow su entrambe le architetture contemporaneamente, assicurando che il codice sia compatibile sia con sistemi x86_64 che ARM.

⚠ Nota: L'esecuzione su Linux ARM64 è attualmente in anteprima pubblica ed è soggetta a modifiche. L'uso di questa architettura consente di testare e ottimizzare le prestazioni dell'applicazione su dispositivi ARM, sempre più diffusi in ambito cloud e edge computing. Per maggiori informazioni fare riferimento alla documentazione About GitHub-hosted runners.

Questa strategia garantisce compatibilità con diverse architetture hardware, migliorando la portabilità dell'applicazione.

Passaggi della Pipeline

La pipeline è composta da una serie di step che permettono di automatizzare il processo di build e distribuzione dell’applicazione. Ogni step viene eseguito sequenzialmente per garantire che il codice venga recuperato, compilato, testato e infine pubblicato come immagine container.

1. Clonazione del Repository

Il primo step assicura che il codice sorgente più recente sia disponibile per la pipeline.

- uses: actions/checkout@v3
  with:
    fetch-depth: 0
YAML

Cosa fa il primo step?

  • Clona l’intero repository, garantendo accesso alla cronologia completa dei commit.
  • Il valore fetch-depth: 0 permette di recuperare tutti i commit, utile per calcoli di differenza tra versioni.

2. Configurazione di GraalVM

GraalVM è essenziale per la creazione di immagini native altamente ottimizzate, riducendo il tempo di avvio e il consumo di memoria dell'applicazione. Per approfondimenti sulla configurazione della GitHub Action graalvm/setup-graalvm@v1, consulta la documentazione ufficiale.

- name: Set up GraalVM
  uses: graalvm/setup-graalvm@v1
  with:
    java-version: '23.0.2'
    distribution: 'graalvm'
    github-token: ${{ secrets.TOKEN_GITHUB }}
    native-image-job-reports: 'true'
YAML

Cosa fa questo secondo step?

  • Installa e configura GraalVM per l’ambiente di esecuzione.
  • Imposta Java 23.0.2 e attiva la generazione di report per la build nativa.

3. Installazione di JBang e Quarkus CLI

Quarkus CLI consente di gestire e costruire applicazioni Quarkus in modo efficiente, semplificando la gestione delle dipendenze e delle configurazioni.

- name: Install JBang and Quarkus CLI
  run: |
    curl -Ls https://sh.jbang.dev | bash -s - trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/
    curl -Ls https://sh.jbang.dev | bash -s - app install --fresh --force quarkus@quarkusio
    echo "PATH=$PATH:/home/runner/.jbang/bin" >> $GITHUB_ENV
YAML

 Cosa fa questo terzo step?

  • Installa JBang, un tool per la gestione di script Java.
  • Installa e configura Quarkus CLI per eseguire build e gestire le dipendenze.

Per ulteriori dettagli sull’installazione della Quarkus CLI, consulta la documentazione ufficiale.

4. Autenticazione su Docker Hub

Prima di pubblicare l’immagine container, è necessario effettuare l’accesso a Docker Hub.

- name: Login to Docker Hub
  uses: docker/login-action@v3
  with:
    username: ${{ secrets.DOCKER_USERNAME }}
    password: ${{ secrets.DOCKER_TOKEN }}
YAML

Cosa fa questo quarto step?

  • Usa le credenziali salvate nei GitHub Secrets per effettuare il login a Docker Hub.
  • Questo passaggio è fondamentale per poter pubblicare l’immagine nel repository remoto.

Per approfondimenti sulla gestione dei secrets in GitHub Actions, consulta la documentazione ufficiale.

5. Creazione dell’artefatto nativo

Questo step compila l’applicazione in un eseguibile nativo utilizzando Quarkus CLI.

- name: Build Native Artifact
  run: |
    quarkus build --native
YAML

Cosa fa questo quinto step?

  • Compila il codice sorgente generando un eseguibile nativo altamente performante.
  • Il codice risultante è ottimizzato per ridurre il consumo di memoria e migliorare il tempo di avvio.

6. Creazione e pubblicazione dell’immagine Docker

Infine, il codice compilato viene trasformato in un’immagine container e pubblicato su Docker Hub.

# Build the native image and push the Docker image
- name: Build Native Image and Push Docker Image
  run: |
    quarkus image build --native \
    -Dquarkus.native.additional-build-args=-march=native,-H:BuildOutputJSONFile=/tmp/native-image-build-output.json \
    -Dquarkus.native.container-build=false \
    -Dquarkus.container-image.push=true \
    -Dquarkus.container-image.registry=docker.io \
    -Dquarkus.container-image.username=${{ secrets.DOCKER_USERNAME }} \
    -Dquarkus.container-image.image=${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}-native:${{ github.ref_name }}-${{ matrix.current_platform }} \
    -Dquarkus.container-image.additional-tags="latest-${{ matrix.current_platform }}" \
    -Dquarkus.container-image.labels.\"org.opencontainers.image.title\"="${{ github.event.repository.name }}" \
    -Dquarkus.container-image.labels.\"org.opencontainers.image.description\"="A native image built with Quarkus CLI" \
    -Dquarkus.container-image.labels.\"org.opencontainers.image.url\"="https://github.com/${{ github.repository }}" \
    -Dquarkus.container-image.labels.\"org.opencontainers.image.source\"="https://github.com/${{ github.repository }}" \
    -Dquarkus.container-image.labels.\"org.opencontainers.image.version\"="${{ github.ref_name }}" \
    -Dquarkus.container-image.labels.\"org.opencontainers.image.created\"="${{ steps.prep.outputs.created }}" \
    -Dquarkus.container-image.labels.\"org.opencontainers.image.revision\"="${{ github.sha }}" \
    -Dquarkus.container-image.labels.\"org.opencontainers.image.authors\"="Antonio Musarra <antonio.musarra@gmail.com>" \
    -Dquarkus.container-image.labels.\"org.opencontainers.image.licenses\"="MIT"
YAML

Cosa fa questo sesto step?

  • Crea un’immagine container contenente l’eseguibile nativo.
  • Applica tag specifici per identificare le versioni dell’immagine.
  • Applica un set di label Open Containers (come description, url, source, etc.).
  • Pubblica automaticamente l’immagine su Docker Hub.

Per ulteriori dettagli sulle specifiche Open Containers, consulta la documentazione ufficiale e in particolare la sezione Annotations sul repository GitHub.

Esecuzione della GitHub Action

La pipeline di GitHub Actions si avvia automaticamente in risposta a eventi specifici, garantendo un processo di build e deploy completamente automatizzato.

1. Quando si Attiva la Pipeline?

Il workflow viene eseguito nei seguenti scenari:

  • Push su develop e main: ogni modifica su queste branch avvia automaticamente il workflow per garantire che il codice aggiornato venga compilato e pubblicato.
  • Pubblicazione di una release: ogni volta che viene creata una nuova release, la pipeline si attiva per generare e distribuire un’immagine nativa della versione stabile.

2. Monitoraggio dell’Esecuzione

Una volta avviata, l’esecuzione della pipeline può essere monitorata direttamente dalla scheda Actions del repository GitHub. Qui è possibile:

  • Osservare lo stato di avanzamento del workflow in tempo reale.
  • Visualizzare i log dettagliati di ogni step per diagnosticare eventuali problemi.
  • Identificare rapidamente errori grazie all’evidenziazione dei messaggi di errore e warning.

Le immagini a seguire evidenziano il processo automatizzato di build e deployment dell’immagine nativa del progetto su Docker Hub, mostrando, sia il workflow GitHub Actions completato con successo, sia il report dettagliato della compilazione GraalVM (grazie al parametro native-image-job-reports:true).

Figura 1 - Workflow GitHub Actions completato con successo
Figura 1 - Workflow GitHub Actions completato con successo

Figura 2 - Report dettagliato della compilazione GraalVM
Figura 2 - Report dettagliato della compilazione GraalVM

Puoi vedere i log completi di questo specifico workflow e job docker (ubuntu-24.04) di cui a seguire è mostrato l'esempio di ciò che vedresti.

Figura 3 - Log del workflow job docker (ubuntu-24-04)
Figura 3 - Log del workflow job docker (ubuntu-24-04)

Nel caso in cui avessi installato il GitHub CLI (gh), potresti usare per esempio, il comando gh run list -b main --workflow build_via_quarkus_cli.yml, per elencare le esecuzioni del workflow GitHub Actions build_via_quarkus_cli.yml sul branch main. 

Questo comando è utile per monitorare rapidamente lo stato delle build eseguite tramite Quarkus CLI senza dover accedere manualmente all’interfaccia web di GitHub Actions. A seguire un esempio di output.

Figura 4 - Output del comando gh run list -b main --workflow build_via_quarkus_cli.yml
Figura 4 - Output del comando gh run list -b main --workflow build_via_quarkus_cli.yml

Al termine del workflow, l’immagine container sarà quindi disponibile nel container registry configurato nel file di workflow, pronta per essere utilizzata in ambienti di sviluppo o produzione. A seguire sono mostrate le due immagini native, una per ARM64 e una per AMD64, contrassegnate dai rispettivi tag.

Figura 5 - Immagini container native pubblicate su Docker Hub tramite la GitHub Action
Figura 5 - Immagini container native pubblicate su Docker Hub tramite la GitHub Action

Conclusioni

Questa pipeline GitHub Actions automatizza l’intero ciclo di sviluppo, dalla compilazione al rilascio dell’immagine container. L’uso combinato di Quarkus CLI, GraalVM e Docker garantisce build efficienti, rapide e compatibili con diverse architetture.

Per approfondire:

Se hai domande o suggerimenti, lascia un commento qui sotto!

 

Antonio Musarra

I began my journey into the world of computing from an Olivetti M24 PC (http://it.wikipedia.org/wiki/Olivetti_M24) bought by my father for his work. Day after day, quickly taking control until … Now doing business consulting for projects in the enterprise application development using web-oriented technologies such as J2EE, Web Services, ESB, TIBCO, PHP.

You may also like...