“Ho caricato l’ordine di lavoro, ma perché non risponde nessuno?”
L’ultima volta avevo scritto con grande entusiasmo il file .gitlab-ci.yml e fatto push. “Adesso il deploy avverrà automaticamente, no?”, e tutto contento ho cliccato sul menu ‘CI/CD > Pipelines’ di GitLab.
Ma sullo schermo non comparve un bel pallino verde di successo, bensì una barra di caricamento che girava all’infinito e il messaggio di stato ‘Pending (in attesa)’. Cliccando sul messaggio, ecco l’avviso:
This job is stuck because the project doesn't have any runners online assigned to it.
Tradotto: “È arrivato del lavoro, ma l’operaio (Runner) che dovrebbe svolgerlo non si è presentato in fabbrica”. Ahia, avevo passato l’ordine di lavoro al direttore di stabilimento (server GitLab), ma non avevo assunto i dipendenti (Runner) che dovevano effettivamente lavorare in fabbrica.

GitLab Runner: le mani e i piedi della pipeline
GitLab si divide essenzialmente in due componenti.
- GitLab Server (sede centrale/direttore di stabilimento): conserva il codice, gestisce lo stato della pipeline e impartisce gli ordini.
- GitLab Runner (filiale/operaio sul campo): viene installato sul server vero e proprio e, ricevuti gli ordini dalla sede centrale, scarica il codice, esegue la build e porta a termine i comandi di deploy.
“Ma non si potrebbe fare in modo che GitLab si colleghi semplicemente al mio server ed effettui il deploy da solo?” A pensarci bene, sarebbe pericolosissimo. Se un sito web su Internet (GitLab) potesse, con un clic, entrare nel computer (server) che ho in camera ed eseguire comandi a piacimento, sarebbe praticamente un ‘hack’. Se qualcuno mi rubasse l’account GitLab, potrebbe trasformare il mio server in una macchina per minare bitcoin.
Per questo GitLab non si collega direttamente al mio server. Piazza invece un ‘agente di identità verificata (Runner)’ che opera solo all’interno del mio server, e affida il lavoro solo tramite questo agente. Tutto il complesso processo di installazione e registrazione che faremo non è altro che la ‘procedura di sicurezza’ per autenticare questo agente.
Fase 1: leggere l’annuncio di lavoro (emissione del token)
Prima di installare il runner, dobbiamo pubblicare presso la sede centrale (GitLab) un ‘annuncio di lavoro’ che dica “ci serve un operaio per il nostro progetto” e ottenere il ‘tesserino di registrazione (Token)’.
Nelle versioni più recenti di GitLab, per ragioni di sicurezza, il modo per consultare il token è un po’ nascosto.
- Apri il progetto su GitLab
- Menu a sinistra: Settings > CI/CD
- Nella sezione Runners, clicca su
Expand - Clicca sul pulsante con i tre puntini (⋮) in alto a destra nella sezione Project runners
Cliccando questo pulsante si apre un menu popup, e qui troviamo le informazioni che cerchiamo. Annotati e copia URL e Registration token.
(Nota: potresti vedere il temibile avviso ‘Support for registration tokens is deprecated’. Significa che il metodo verrà presto dismesso, ma per ora è ancora supportato per retrocompatibilità: niente panico, copia pure il token.)
[Suggerimento] Hai più progetti? (Group Runner) Se come me gestisci più progetti (frontend, backend, ecc.) raggruppati insieme, registrare un runner per ogni progetto è inefficiente. In questo caso, anziché nelle impostazioni di progetto, registra il runner dal menu Group Settings > CI/CD. Un ‘Group Runner’ creato così riesce a gestire da solo tutti i lavori dei progetti appartenenti al gruppo. (Io ho molti progetti, quindi ho scelto questa strada.)

Fase 2: assumere l’operaio (installazione del Runner)
Ora installiamo davvero il runner sul server Linux (o sul nostro PC). Il modo più pulito è, ovviamente, usare il nostro amato ‘Docker’.
# 1. Avvia il container GitLab Runner
docker run -d --name gitlab-runner --restart always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v gitlab-runner-config:/etc/gitlab-runner \
gitlab/gitlab-runner:latest
-v /var/run/docker.sock:/var/run/docker.sock: questa parte è importante. Il runner deve avviare a sua volta altri container Docker (quelli per la build), quindi gli condividiamo il socket Docker dell’host. (approccio Docker in Docker)
Fase 3: firmare il contratto di lavoro (registrazione del Runner)
Aver installato il runner non basta. Serve la procedura per registrare (Register) questo runner sul server GitLab dichiarando “io sono un operaio del progetto A”.
Entriamo nel container del runner appena avviato ed eseguiamo il comando di registrazione.
# Esegui il comando di registrazione dentro il container del runner
docker exec -it gitlab-runner gitlab-runner register
Ora nel terminale inizia una sequenza di domande tipo “venti domande”. Basta inserire le informazioni viste nella Fase 1.
- Enter the GitLab instance URL:
https://gitlab.com/(oppure l’indirizzo del tuo GitLab privato)
- Enter the registration token:
- (incolla il token copiato prima)
- Enter a description for the runner:
my-runner-01(un nome qualsiasi, purché facile da riconoscere)
- Enter tags for the runner:
- (puoi saltarlo premendo Invio. Serve quando vuoi affidare al runner solo i job con determinati tag.)
- Enter an executor:
docker(visto che faremo la build sopra Docker, inseriamo docker.)
- Enter the default Docker image:
docker:latest(l’immagine da usare come predefinita)
“Runner registered successfully.” Quando appare questo messaggio, l’assunzione è completata! Ora aggiorna la schermata di GitLab e vedrai il runner con la spia verde accesa che grida “Sono pronto (Online)”.

Fase 4: pipeline in moto!
Nel momento in cui il runner viene registrato, la pipeline che era ferma (Pending) inizia a muoversi automaticamente. Running… e poco dopo Passed!
Io non ho fatto nulla, eppure la macchina ha eseguito i test, fatto la build, creato l’immagine e l’ha caricata nel repository da sola. Aprendo il terminale per controllare i log, vedo che tutto è stato completato in modo molto più rapido e preciso rispetto a quando lo facevo a mano.
“Wow… funziona davvero?”
Il deploy manuale che richiedeva 10 minuti ora finisce con un solo git push. Adesso posso lanciare il deploy e andarmi a prendere un caffè.
Consiglio pratico: problema di permessi Docker (Permission Denied)
C’è un errore che si incontra al 99% quando si configura il runner per la prima volta: dial unix /var/run/docker.sock: connect: permission denied
È un problema che si verifica quando il runner cerca di usare i comandi Docker ma non ne ha i permessi. In questi casi bisogna aprire il file di configurazione del gitlab-runner (config.toml) e attivare l’opzione privileged = true.
# /etc/gitlab-runner/config.toml (file di config del runner)
[[runners]]
name = "my-runner-01"
executor = "docker"
[runners.docker]
privileged = true # Bisogna cambiare questa parte in true affinché Docker-in-Docker funzioni correttamente. # …
In conclusione: ora posso staccare
Finalmente ho il mio personale ‘robot del deploy’. Ora posso concentrarmi solo a scrivere codice. Le noiose e ripetitive operazioni di verifica e deploy le svolgerà al posto mio il mio fedele robot (Runner).
Manca però ancora il 2%. Al momento la pipeline parte ogni volta che si fa push sul branch master. “E se volessi deployare automaticamente sul server di sviluppo (dev), ma sul server di produzione (prod) solo quando premo io il ‘pulsante di approvazione’?”
La prossima volta vedremo come controllare la pipeline in modo più intelligente, con la ‘strategia di deploy per branch’ e la ‘procedura di approvazione manuale (Manual)’.


