Usare una container image come runner di GitHub Actions

di Matteo Tumiati, in DevOps,

Quando utilizziamo un workflow in GitHub, ci dobbiamo preoccupare di specificare il runner (o l'agent) all'interno del quale verrà eseguito il processo. Questo si divide principalmente in due scelte: quella on-prem e quella hosted, gestita da GitHub stessa. Nel primo caso, ci dobbiamo gestire noi hardware e software. Nel secondo, invece, abbiamo una VM già pre-configurata con una serie di software già presenti. Tra le altre differenze che troviamo, nel caso dell'on-prem, siamo più esposti a rischi di sicurezza, poiché, di fatto, non c'è il riciclo dell'hardware che, infatti, potrebbe essere utilizzato da più workflow all'interno della nostra istanza di GitHub (per esempio fra più repository), mentre condividono lo stesso storage. Allo stesso modo, la gestione delle dipendenze è un po' più complessa, in quanto se vengono richieste, per esempio, molte versioni di SDK, librerie e quant'altro necessario allo sviluppo, diventa più complicato manutenere tutta l'infrastruttura.

Proprio per gestire questi casi più complessi, dove magari si vuole il meglio di un ambiente e dell'altro, si può far riferimento ad una terza opzione: il Docker container. Infatti, è possibile creare una immagine di Docker e utilizzarla per eseguire il nostro workflow. Vediamo un esempio:

name: CI
on:
  push:
    branches: [ main ]
jobs:
  container-test-job:
    runs-on: ubuntu-latest
    container:
      image: node:18
      env:
        NODE_ENV: development
      ports:
        - 80
      volumes:
        - my_docker_volume:/volume_mount
      options: --cpus 1
    steps:
      - name: Check for dockerenv file
        run: (ls /.dockerenv && echo Found dockerenv) || (echo No dockerenv)

In questo caso, il runner è una macchina hosted basata su Ubuntu, ma l'esecuzione del workflow viene "demandata" al container che viene messo in esecuzione, ovvero una distribuzione di NodeJS. Stessa cosa potrebbe avvenire nel sistema on-prem. Per ridurre al minimo il rischio che un workflow "contamini" un altro che condivide lo stesso storage, artifact, librerie o altro, è fondamentale fare in modo che il flusso giri su un sistema che può essere eliminato alla fine del workflow e riutilizzato. In questo caso Docker è l'ideale, poiché di fatto il container è stateless.

Come si può vedere dall'esempio, poi, è anche possibile andare a customizzare l'immagine base. Di fatto, quindi, può essere utile costruire una immagine base per tutta la mia organizzazione aziendale, in cui vado ad installare le dipendenze necessarie ad eseguire i miei processi. Eventualmente, per ciascun workflow, vado poi ad impostare la porta di esecuzione, variabili d'ambiente e altri setting secondo le mie esigenze.

Nota di chiusura riguarda invece il tema consumi: è chiaro che più piccola sarà l'immagine Docker, prima il workflow potrà metterlo in esecuzione e più tempo (e costi) risparmieremo per l'esecuzione della stessa, che ci verranno comunque conteggiati nella fattura a fine mese.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi