GitLab Runner: Creazione di immagini Docker

Crea e pubblica immagini Docker dai tuoi pipeline GitLab CI/CD utilizzando il tuo runner Stackhero e Docker-in-Docker

👋 Benvenuto nella documentazione di Stackhero!

Stackhero ti offre una soluzione GitLab Runner cloud facile da usare, progettata per gestire in modo efficiente i tuoi job GitLab CI/CD. Ecco cosa puoi aspettarti:

  • Minuti CI/CD illimitati: nessuna fatturazione al minuto, le tue pipeline possono essere eseguite ogni volta che ne hai bisogno.
  • Job concorrenti multipli: esegui più job contemporaneamente per velocizzare l'intera pipeline.
  • Docker executor con supporto Docker-in-Docker: semplifica la creazione e il push delle tue immagini container.
  • Compatibile sia con GitLab.com che con qualsiasi istanza GitLab self-managed.
  • Una VM privata e dedicata alimentata da dischi NVMe/SSD veloci per build affidabili e costanti.
  • Disponibile sia nelle regioni 🇪🇺 Europa che 🇺🇸 USA.

Risparmia tempo: puoi collegare il tuo primo GitLab Runner e iniziare a eseguire pipeline in pochi minuti!

Quando utilizzi uno Stackhero GitLab Runner, i job vengono eseguiti con il Docker executor. Questo significa che ogni job parte in un nuovo container basato sull'image che specifichi. Se desideri costruire le tue immagini Docker all'interno della pipeline, puoi sfruttare Docker-in-Docker (DinD). Questa configurazione consente a un demone Docker di essere eseguito insieme al tuo job, permettendoti di eseguire comandi come docker build e docker push direttamente nella pipeline.

Uno dei grandi vantaggi è che il tuo runner dispone di minuti CI/CD illimitati. Puoi costruire immagini tutte le volte che vuoi. Inoltre, dato che la cache di build risiede sul disco dedicato del runner, le build ripetute possono riutilizzare i layer precedenti, accelerando notevolmente i tuoi pipeline.

Ecco un esempio di .gitlab-ci.yml che puoi aggiungere al tuo repository. Questa configurazione costruisce il Dockerfile presente nella root del tuo progetto:

build-image:
  stage: build
  image: docker:27
  services:
    - docker:27-dind
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  before_script:
    - docker info
  script:
    # Sostituisci "my-image" con il nome desiderato:
    - docker build -t my-image .
    # Facoltativamente, puoi eseguire un rapido smoke test sull'immagine appena creata:
    # - docker run --rm my-image /path/to/tests

In questa configurazione, il servizio docker:27-dind avvia il demone Docker. La variabile DOCKER_TLS_CERTDIR: "/certs" abilita una connessione TLS sicura tra il job e il demone Docker.

GitLab mette a disposizione diverse variabili predefinite (CI_REGISTRY, CI_REGISTRY_USER, CI_REGISTRY_PASSWORD, CI_REGISTRY_IMAGE) così che la pipeline possa autenticarsi e pubblicare immagini nel container registry del progetto senza bisogno di segreti aggiuntivi.

Ecco un esempio di job che costruisce e pubblica la tua immagine:

build-and-push:
  stage: build
  image: docker:27
  services:
    - docker:27-dind
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  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

Se desideri pubblicare le immagini su un altro registry (come Docker Hub o un registry privato), puoi salvare le relative credenziali come variabili CI/CD e utilizzarle con docker login nello stesso modo.

Poiché il disco del runner è persistente tra i pipeline, puoi velocizzare le build riutilizzando i layer delle immagini precedenti come cache. Ecco come configurarlo:

build-cached:
  stage: build
  image: docker:27
  services:
    - docker:27-dind
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
  script:
    # Prova a scaricare l'immagine "latest" per alimentare la cache (va bene se non esiste ancora):
    - 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 ai tuoi pipeline di completarsi più rapidamente nel tempo, sfruttando al massimo la cache dei layer Docker.

Il tuo piano determina quanti job possono essere eseguiti contemporaneamente. I job all'interno dello stesso stage vengono avviati insieme, fino al limite di concorrenza previsto. Questo significa che uno stage con più job indipendenti si conclude non appena termina il job più lento, invece di eseguire tutti i job in sequenza.

Ecco un esempio semplice:

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 3 o superiore, i job unit, integration ed e2e verranno eseguiti tutti contemporaneamente.

Se desideri approfondire la creazione di immagini Docker in CI, consulta la documentazione ufficiale di GitLab.