GitLab Runner: Creazione di immagini Docker
Crea e pubblica immagini Docker in modo efficiente dalle tue pipeline GitLab CI/CD utilizzando i runner Stackhero e Docker-in-Docker
👋 Benvenuto nella documentazione di Stackhero!
Stackhero offre una soluzione GitLab Runner cloud semplice che rende l'esecuzione dei tuoi job GitLab CI/CD efficiente e senza complicazioni. Ecco cosa puoi aspettarti:
- Minuti CI/CD illimitati: esegui le tue pipeline tutte le volte che vuoi, senza costi al minuto o spese impreviste.
- Più job in contemporanea: accelera lo sviluppo eseguendo diversi job in parallelo.
- L'executor Docker con supporto Docker-in-Docker: costruisci e pubblica facilmente immagini container come parte del tuo processo CI/CD.
- Funziona perfettamente sia con GitLab.com che con istanze GitLab self-managed.
- Un'infrastruttura privata e dedicata con storage NVMe/SSD veloce garantisce prestazioni di build stabili e prevedibili.
- Disponibile nelle regioni 🇪🇺 Europa e 🇺🇸 USA per soddisfare le esigenze del tuo team.
Risparmia tempo: puoi collegare il tuo primo GitLab Runner e iniziare a eseguire pipeline in pochi minuti!
Introduzione
Con uno Stackhero GitLab Runner, ogni job viene eseguito all'interno di un container isolato tramite l'executor Docker. Puoi creare le tue immagini Docker direttamente nella pipeline abilitando Docker-in-Docker (DinD). Questa configurazione avvia un demone Docker accanto al tuo job, consentendoti di eseguire i comandi docker build e docker push come parte del processo CI/CD.
Ogni esecuzione beneficia di minuti CI/CD illimitati: puoi effettuare build tutte le volte che vuoi, senza preoccuparti di limiti di utilizzo. Il build cache viene memorizzato sul disco dedicato del runner, il che significa che le build ripetute possono riutilizzare i layer precedenti. Questo riduce notevolmente i tempi di build e accelera il completamento delle pipeline.
Creazione di un'immagine Docker con Docker-in-Docker
Puoi aggiungere il seguente esempio di .gitlab-ci.yml al tuo repository. Questa configurazione costruisce il Dockerfile presente nella root del progetto:
build-image:
stage: build
image: docker:29
services:
- name: docker:29-dind
alias: docker
variables:
DOCKER_HOST: "tcp://docker:2375"
DOCKER_TLS_CERTDIR: ""
before_script:
- docker info
script:
# Sostituisci "my-image" con il nome desiderato:
- docker build -t my-image .
# Facoltativamente, esegui un test rapido sull'immagine appena creata:
# - docker run --rm my-image /path/to/tests
In questo esempio utilizziamo la versione 29 dell'immagine Docker. Puoi scegliere una versione più recente non appena disponibile. Trovi i tag più aggiornati sulla pagina ufficiale Docker image.
In questa configurazione, il servizio docker:29-dind avvia un demone Docker accanto al job, e DOCKER_HOST: "tcp://docker:2375" indica alla CLI docker di utilizzarlo. Imposta sempre DOCKER_HOST quando dichiari un servizio docker:dind: senza questa variabile, la CLI si collega silenziosamente a un altro demone, quindi la build può andare a buon fine anche se il servizio è configurato in modo errato, nascondendo problemi reali (e interrompendo strumenti come Testcontainers che dipendono dal servizio). DOCKER_TLS_CERTDIR: "" permette la connessione tramite la porta non-TLS 2375 sulla rete interna del job.
In alternativa, puoi omettere il blocco services e le due variabili: il runner Stackhero espone anche un demone Docker già pronto tramite un socket montato, quindi un semplice docker build funziona senza configurazioni aggiuntive.
Esecuzione dei test con Testcontainers
Testcontainers è una libreria di testing, disponibile per Java, Go, Node.js, Python, .NET e altri linguaggi, che avvia servizi reali come container Docker temporanei durante l'esecuzione dei test. Invece di simulare un database o un message broker, i test di integrazione interagiscono con una vera istanza di PostgreSQL, MySQL, Redis o Kafka, creata prima dei test e rimossa subito dopo. È particolarmente popolare nei progetti Java e Spring.
Testcontainers necessita di un demone Docker, quindi funziona con la stessa configurazione Docker-in-Docker vista sopra. Non sono richieste variabili aggiuntive:
test:
stage: test
# Usa l'immagine necessaria per i tuoi test (ad esempio una JDK), non necessariamente l'immagine docker:
image: gradle:jdk21
services:
- name: docker:29-dind
alias: docker
variables:
DOCKER_HOST: "tcp://docker:2375"
DOCKER_TLS_CERTDIR: ""
script:
- gradle test
Testcontainers legge la variabile DOCKER_HOST per individuare il demone, e riutilizza lo stesso hostname docker per raggiungere le porte pubblicate dai container che avvia. Entrambe le funzionalità sono operative perché l'alias docker viene risolto sulla rete del job.
Mantieni
DOCKER_HOSTnei job che utilizzano Testcontainers. Senza questa variabile, Testcontainers utilizza il socket Docker montato dal runner e poi tenta di raggiungere i container di test tramite l'indirizzo IP host, a cui il job non può connettersi. Il sintomo tipico è il fallimento del container helper Ryuk conWait strategy failed. Container is removed, oppureTimed out waiting for log output matching '.*Started.*'.
Push verso il container registry di GitLab
GitLab mette a disposizione variabili predefinite (CI_REGISTRY, CI_REGISTRY_USER, CI_REGISTRY_PASSWORD, CI_REGISTRY_IMAGE) affinché la pipeline possa autenticarsi e pubblicare immagini nel container registry del progetto in modo sicuro. Non sono necessari segreti aggiuntivi.
Ecco un esempio di job che costruisce e pubblica la tua immagine:
build-and-push:
stage: build
image: docker:29
services:
- name: docker:29-dind
alias: docker
variables:
DOCKER_HOST: "tcp://docker:2375"
DOCKER_TLS_CERTDIR: ""
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
script:
- docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" .
- docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
# Se sei sul branch di default, puoi anche taggare e pubblicare "latest":
- |
if [ "$CI_COMMIT_BRANCH" = "$CI_DEFAULT_BRANCH" ]; then
docker tag "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" "$CI_REGISTRY_IMAGE:latest"
docker push "$CI_REGISTRY_IMAGE:latest"
fi
Per pubblicare le immagini su un altro registry (come Docker Hub o un registry privato), puoi memorizzare le credenziali come variabili CI/CD e utilizzarle con docker login allo stesso modo.
Accelerare le build ripetute
Il disco del runner persiste tra le pipeline, consentendo di riutilizzare i layer delle immagini come cache di build. Questo può rendere le build ripetute molto più rapide. Ecco un esempio di configurazione:
build-cached:
stage: build
image: docker:29
services:
- name: docker:29-dind
alias: docker
variables:
DOCKER_HOST: "tcp://docker:2375"
DOCKER_TLS_CERTDIR: ""
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
script:
# Recupera l'ultima immagine per inizializzare la cache (se esiste):
- docker pull "$CI_REGISTRY_IMAGE:latest" || true
- docker build --cache-from "$CI_REGISTRY_IMAGE:latest" -t "$CI_REGISTRY_IMAGE:latest" .
- docker push "$CI_REGISTRY_IMAGE:latest"
Questo approccio permette di sfruttare la cache dei layer Docker, ricostruendo solo i layer nuovi o modificati.
Esecuzione di job in parallelo
Il tuo piano determina quanti job possono essere eseguiti contemporaneamente. I job appartenenti allo stesso stage vengono avviati insieme, fino al limite di concorrenza previsto. Questo significa che più job indipendenti possono essere eseguiti in parallelo e terminare non appena il più lento si conclude, senza dover attendere la fine sequenziale di ciascun job.
Esempio:
stages:
- test
unit:
stage: test
image: node:22
script: npm run test:unit
integration:
stage: test
image: node:22
script: npm run test:integration
e2e:
stage: test
image: node:22
script: npm run test:e2e
Se imposti la concorrenza a 1 o superiore, i job unit, integration ed e2e verranno eseguiti contemporaneamente.
Per ulteriori dettagli sulla creazione di immagini Docker nelle pipeline GitLab CI/CD, puoi consultare la documentazione ufficiale GitLab sull'utilizzo dei Docker build.