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
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Utilizzare zizmor per rendere più sicuri i workflow di GitHub
Eseguire i pre-commit hook di git con dependabot
Filtrare i dati in ASP.NET Core usando OpenTelemetry su Azure Monitor
Ciclo di vita risorse con .NET Aspire
Pubblicare un MCP Server in GitHub MCP Registry
Raggruppamento degli aggiornamenti di dipendenze tra directory in un monorepo con Dependabot
Stop Building Chatbots. Build a team
Creare un indice su una colonna JSON in SQL Server
Applicare il progressive enhancement in applicazioni web
Utilizzare i command service nei test con .NET Aspire
GitHub Quick Review per la valutazione dello stato di compliance dell'organizzazione aziendale


