Come creare immagini Docker in una pipeline CI GitLab

0
284

Un caso d'uso comune per le pipeline CI è la creazione delle immagini Docker che hai ;Utilizzerò per distribuire la tua applicazione. GitLab CI è un'ottima scelta per questo in quanto supporta un servizio pull proxy integrato, il che significa pipeline più veloci e un registro integrato per archiviare le immagini create.

In questa guida, ti mostreremo come configurare build Docker che utilizzano entrambe le funzionalità di cui sopra. I passaggi che devi eseguire variano leggermente a seconda del tipo di executor di GitLab Runner che utilizzerai per la tua pipeline. Di seguito tratteremo gli esecutori Shell e Docker.

Creazione con l'esecutore Shell

Se si’ usando l'esecutore Shell, assicurati di avere Docker installato sulla macchina che ospita il tuo runner. L'esecutore funziona eseguendo i normali comandi della shell utilizzando il binario docker sull'host di Runner.

Vai al repository Git per il progetto per il quale desideri creare immagini. Crea un file .gitlab-ci.yml nella radice del repository. Questo file definisce la pipeline CI GitLab che verrà eseguita quando esegui il push delle modifiche al tuo progetto.

Aggiungi il seguente contenuto al file:

fasi: – build docker_build: stage: build script: – docker build -t example.com/example-image:latest . – docker push example.com/example-image:latest

Questa configurazione semplicistica è sufficiente per dimostrare le basi delle build di immagini basate su pipeline. GitLab clona automaticamente il tuo repository Git nell'ambiente di build, quindi l'esecuzione della build docker utilizzerà il Dockerfile del tuo progetto e renderà disponibile il contenuto del repository come contesto di build.

Pubblicità

Dopo la build viene completata, puoi eseguire il push dell'immagine nella finestra mobile nel registro. Altrimenti sarebbe disponibile solo per l'installazione Docker locale che ha eseguito la build. Se stai utilizzando un registro privato, esegui prima il login Docker per fornire i dettagli di autenticazione corretti:

script: – login Docker -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASSWORD

Definisci i valori delle due variabili credenziali andando su Impostazioni > CI/CD > Variabili nell'interfaccia utente web di GitLab. Fai clic sul pulsante blu “Aggiungi variabile” per creare una nuova variabile e assegnare un valore. GitLab renderà disponibili queste variabili nell'ambiente shell utilizzato per eseguire il lavoro.

Creazione con Docker Executor

L'esecutore Docker di GitLab Runner è comunemente usato per fornire un ambiente completamente pulito per ogni lavoro. Il lavoro verrà eseguito in un contenitore isolato, quindi il binario della finestra mobile sull'host Runner sarà inaccessibile.

L'esecutore Docker offre due possibili strategie per creare l'immagine: utilizzare Docker-in-Docker o collegare il socket Docker dell'host all'ambiente di compilazione di Runner. Quindi utilizzi l'immagine del contenitore Docker ufficiale come immagine del tuo lavoro, rendendo disponibile il comando docker nello script CI.

Docker-in-Docker

L'utilizzo di Docker-in-Docker (DinD) per creare le immagini offre un ambiente completamente isolato per ogni lavoro. Il processo Docker che esegue la compilazione sarà un figlio del contenitore che GitLab Runner crea sull'host per eseguire il processo CI.

È necessario registrare l'esecutore Docker di GitLab Runner con la modalità privilegiata abilitata per utilizzare DinD . Aggiungi il flag –docker-privileged quando registri il tuo corridore:

sudo gitlab-runner register -n –url https://example.com –registration-token $GITLAB_REGISTRATION_TOKEN –executor docker –description “Docker Runner” –docker-image “docker:20.10” –docker-volumes “/certs/client” –docker-privileged Pubblicità

All'interno della pipeline CI, aggiungi l'immagine docker:dind come servizio. Ciò rende Docker disponibile come immagine separata collegata all'immagine del lavoro. Potrai utilizzare il comando docker per creare immagini utilizzando l'istanza Docker nel contenitore docker:dind.

servizi: – docker:dind docker_build: stage: build image: docker:latest script: – docker build -t esempio-immagine:latest .

L'utilizzo di DinD ti offre build completamente isolate che non possono influire l'una sull'altra o sul tuo host. Lo svantaggio principale è un comportamento di memorizzazione nella cache più complicato: ogni lavoro ottiene un nuovo ambiente in cui i livelli precedentemente creati non sono accessibili. Puoi risolvere parzialmente questo problema provando a estrarre la versione precedente dell'immagine prima di creare, quindi utilizzando il flag –cache-from build per rendere disponibili i livelli dell'immagine estratta come origine cache:

docker_build : stage: build image: docker:ultimo script: – docker pull $CI_REGISTRY_IMAGE:latest || true – docker build –cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:latest .

Socket Bind Mounts

Il montaggio del socket Docker del tuo host nell'ambiente del tuo lavoro è un'opzione alternativa quando utilizzi l'esecutore Docker. Questo ti offre una memorizzazione nella cache senza interruzioni ed elimina la necessità di aggiungere il servizio docker:dind alla tua configurazione CI.

Per configurarlo, registra il tuo Runner con un flag dei volumi docker che leghi gli host Socket Docker su /var/run/docker.sock all'interno dei contenitori di lavoro:

sudo gitlab-runner register -n –url https://example.com –registration-token $GITLAB_REGISTRATION_TOKEN –executor docker –description “Docker Runner” –docker-image “docker:20.10” –docker-volumes /var/run/docker.sock:/var/run/docker.sock

Ora i lavori eseguiti con l'immagine della finestra mobile potranno utilizzare normalmente il binario della finestra mobile. Le operazioni si verificheranno effettivamente sul computer host, diventando fratelli del contenitore del lavoro anziché figli.

Questo è effettivamente simile all'utilizzo dell'esecutore shell con l'installazione Docker del tuo host. Le immagini risiedono sull'host, facilitando l'uso senza interruzioni della normale memorizzazione nella cache del livello di build della finestra mobile.

Pubblicità

Sebbene questo approccio possa portare a prestazioni più elevate, meno configurazione e nessuno dei limiti di DinD, ha i suoi problemi unici. Le più importanti tra queste sono le implicazioni sulla sicurezza: i lavori potrebbero eseguire comandi Docker arbitrari sul tuo host Runner, quindi un progetto dannoso nella tua istanza GitLab potrebbe eseguire docker run -it dannoso-image:latest o docker rm -f $(docker ps -a ) con conseguenze devastanti.

GitLab avverte inoltre che l'associazione del socket può causare problemi quando i lavori vengono eseguiti contemporaneamente. Ciò si verifica quando si fa affidamento sulla creazione di contenitori con nomi specifici. Se due istanze di un lavoro vengono eseguite in parallelo, la seconda fallirà poiché il nome del contenitore esiste già sul tuo host.

Dovresti considerare l'utilizzo di DinD se prevedi che uno di questi problemi sarà problematico. Sebbene DinD non sia più generalmente consigliato, può avere più senso per le istanze GitLab pubbliche che eseguono lavori CI simultanei.

Invio di immagini al registro di GitLab

I progetti GitLab hanno l'opzione di un registro integrato che puoi utilizzare per archiviare le tue immagini. Puoi visualizzare il contenuto del registro accedendo a Pacchetti e amp; Registri > Registro dei contenitori nella barra laterale del tuo progetto. Se non vedi questo link, abilita il registro andando su Impostazioni > Generale > Visibilità, progetto, funzionalità e amp; Autorizzazioni e attivazione del “Registro contenitori” attiva/disattiva.

 

GitLab imposta automaticamente le variabili di ambiente nei tuoi lavori CI che ti consente di fare riferimento al registro dei contenitori del tuo progetto. Regola la sezione dello script per accedere al registro ed eseguire il push della tua immagine:

script: – docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY – docker build -t $CI_REGISTRY_IMAGE:latest . – push della finestra mobile $CI_REGISTRY_IMAGE:latest

GitLab genera un set sicuro di credenziali per ciascuno dei tuoi lavori CI. La variabile di ambiente $CI_JOB_TOKEN conterrà un token di accesso che il lavoro può utilizzare per connettersi al registro come utente gitlab-ci-token. L'URL del server del registro è disponibile come $CI_REGISTRY.

Pubblicità

La variabile finale, $CI_REGISTRY_IMAGE, fornisce il percorso completo del registro del contenitore del tuo progetto. Questa è una base adatta per i tuoi tag immagine. Puoi estendere questa variabile per creare sottorepository, come $CI_REGISTRY_IMAGE/production/api:latest.

 

Altri client Docker possono estrarre immagini dal registro eseguendo l'autenticazione tramite un token di accesso. Puoi generarli nelle Impostazioni del tuo progetto > Schermata di accesso ai token. Aggiungi l'ambito read_registry, quindi utilizza le credenziali visualizzate per accedere alla finestra mobile al registro del tuo progetto.

Utilizzo del proxy di dipendenza di GitLab

h2>

Il proxy di dipendenza di GitLab fornisce un livello di memorizzazione nella cache per le immagini upstream che estrai da Docker Hub. Ti aiuta a rimanere entro i limiti di velocità di Docker Hub estraendo il contenuto delle immagini solo quando sono effettivamente cambiate. Ciò migliorerà anche le prestazioni delle tue build.

Il proxy di dipendenza viene attivato a livello di gruppo GitLab andando su Impostazioni > Pacchetti & Registri > Procura di dipendenza. Una volta abilitato, anteporre i riferimenti alle immagini nel file .gitlab-ci.yml con $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX per estrarli tramite il proxy:

docker_build: stage: build image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/docker:latest services: – nome: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/docker:dind alias: docker

Questo è tutto quello che c'è da fare! GitLab Runner accede automaticamente al registro del proxy di dipendenza, quindi non è necessario fornire manualmente le credenziali.

GitLab ora memorizza nella cache le tue immagini, offrendoti prestazioni migliorate e resilienza alle interruzioni di rete. Si noti che anche la definizione dei servizi ha dovuto essere modificata – le variabili di ambiente non funzionano con il modulo inline utilizzato in precedenza, quindi è necessario specificare il nome completo dell'immagine, quindi un alias di comando a cui fare riferimento nella sezione dello script.

Pubblicità

Anche se ora abbiamo impostato il proxy per le immagini utilizzate direttamente dalle nostre fasi di lavoro, è necessario altro lavoro per aggiungere il supporto per l'immagine di base nel Dockerfile da creare. Un'istruzione regolare come questa non ha superato il proxy:

FROM ubuntu:latest

Per aggiungere questo pezzo finale, usa gli argomenti build di Docker per rendere disponibile l'URL del proxy di dipendenza durante l'esecuzione il Dockerfile:

ARG GITLAB_DEPENDENCY_PROXY FROM ${GITLAB_DEPENDENCY_PROXY}/ubuntu:latest

Quindi modifica il comando di build della finestra mobile per definire il valore della variabile:

script: > – build docker –build-arg GITLAB_DEPENDENCY_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX} -t esempio-immagine:latest .

Ora anche la tua immagine di base verrà inserita nel proxy di dipendenza.

Riepilogo

Le build di immagini Docker sono facilmente integrabili nelle pipeline CI di GitLab. Dopo la configurazione iniziale di Runner, i comandi docker build e docker push nella sezione script del tuo lavoro sono tutto ciò che ti serve per creare un'immagine con il Dockerfile nel tuo repository. Il registro dei contenitori integrato di GitLab ti offre uno spazio di archiviazione privato per le immagini del tuo progetto.

Oltre alle build di base, vale la pena integrare il proxy di dipendenza di GitLab per accelerare le prestazioni ed evitare di raggiungere i limiti di velocità di Docker Hub. Dovresti anche verificare la sicurezza della tua installazione valutando se il metodo selezionato consente a progetti non attendibili di eseguire comandi sul tuo host Runner. Sebbene abbia i suoi problemi, Docker-in-Docker è l'approccio più sicuro quando la tua istanza GitLab è pubblicamente accessibile o accessibile da una vasta base di utenti.