”Jag har lagt upp arbetsordern, varför händer inget?”
Förra gången skrev jag entusiastiskt en .gitlab-ci.yml-fil och gjorde push. ”Nu kör väl deploy automatiskt?”, tänkte jag förväntansfullt och klickade på menyn ’CI/CD > Pipelines’ i GitLab.
Men det som dök upp på skärmen var ingen grön bock för lyckad körning, utan en laddningssnurra som snurrade i evighet och statusmeddelandet ’Pending (Väntande)’. När jag klickade på meddelandet såg jag den här varningen:
This job is stuck because the project doesn't have any runners online assigned to it.
I klartext: ”Det har kommit in jobb, men arbetaren (Runner) som ska utföra det har inte dykt upp på jobbet”. Hoppsan — jag hade slängt arbetsordern till fabrikschefen (GitLab-servern), men glömt att anställa själva arbetarna (Runners) som faktiskt skulle jobba i fabriken.

GitLab Runner: pipelinens händer och fötter
GitLab delas i grova drag in i två komponenter.
- GitLab Server (huvudkontoret/fabrikschefen): Lagrar koden, håller koll på pipelinens status och delar ut instruktioner.
- GitLab Runner (filialen/arbetaren på plats): Installeras på själva servern, tar emot huvudkontorets instruktioner, hämtar koden, bygger den och utför deploykommandona.
”Kan inte GitLab bara logga in på min server själv och deploya?” Om man tänker efter är det livsfarligt. Om en webbplats på internet (GitLab) bara kunde, med ett knapptryck, gå in i datorn (servern) på mitt rum och köra vilka kommandon den ville? Det vore i princip ’hackning’. Om någon kapar mitt GitLab-konto skulle de kunna göra om min server till en bitcoin-mining-maskin.
Därför kopplar GitLab inte upp sig direkt mot min server. I stället placerar man ut ett ’ombud med verifierad identitet (Runner)’ som bara kör inuti min server, och delegerar arbete enbart via det ombudet. Den krångliga installations- och registreringsprocessen vi nu ska gå igenom är just ’säkerhetsförfarandet’ för att autentisera detta ombud.
Steg 1: kolla jobbannonsen (utfärda token)
Innan vi installerar runnern måste vi först gå till huvudkontoret (GitLab) och lägga ut en ’jobbannons’ med texten ”vi behöver en arbetare till vårt projekt” och hämta ut ett ’registreringsbevis (Token)’.
I de senaste GitLab-versionerna är sättet att kolla token lite undanstoppat av säkerhetsskäl.
- Gå in på GitLab-projektet
- Vänstermenyn: Settings > CI/CD
- Fäll ut avsnittet Runners genom att klicka på
Expand - Klicka på knappen med tre prickar (⋮) uppe till höger i avsnittet Project runners
När du klickar på den knappen öppnas en popupmeny — och här finns informationen vi letar efter. Notera och kopiera URL och Registration token.
(Obs: den otäcka varningen ’Support for registration tokens is deprecated’ kan dyka upp. Det betyder att metoden snart kommer försvinna, men den stöds fortfarande av kompatibilitetsskäl — så ingen panik, kopiera bara token.)
[Tips] Har du flera projekt? (Group Runner) Om du, som jag, hanterar flera projekt (frontend, backend osv.) samlade i en grupp är det ineffektivt att registrera en runner per projekt. Då registrerar du i stället runnern under Group Settings > CI/CD i stället för i projektinställningarna. En sådan ’Group Runner’ kan ensam ta hand om alla jobb från alla projekt som tillhör gruppen. (Jag har många projekt, så jag valde det här upplägget.)

Steg 2: anställa arbetaren (installera Runner)
Nu installerar vi runnern på riktigt på en Linux-server (eller på den egna datorn). Det renaste sättet är förstås att använda vår älskade ’Docker’.
# 1. Kor GitLab Runner-containern
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: Det här är viktigt. Eftersom runnern i sin tur måste kunna starta andra Docker-containrar (för bygget) delar vi värddatorns Docker-socket med den. (Docker in Docker-metoden)
Steg 3: skriva på anställningsavtalet (registrera Runner)
Det räcker inte med att ha installerat runnern. Vi behöver också registrera (Register) den hos GitLab-servern och säga ”jag är en arbetare för projekt A”.
Vi går in i runner-containern vi just startade och kör registreringskommandot.
# Kor registreringskommandot inuti runner-containern
docker exec -it gitlab-runner gitlab-runner register
Nu startar en serie ’tjugo frågor’ i terminalen. Du fyller helt enkelt i det vi såg i Steg 1.
- Enter the GitLab instance URL:
https://gitlab.com/(eller adressen till din privata GitLab)
- Enter the registration token:
- (Klistra in token som du kopierade nyss)
- Enter a description for the runner:
my-runner-01(vad som helst, bara namnet är lätt att känna igen)
- Enter tags for the runner:
- (Kan hoppas över genom att trycka Enter. Används när runnern bara ska ta jobb som har vissa taggar.)
- Enter an executor:
docker(vi ska bygga ovanpå Docker, så vi skriver docker.)
- Enter the default Docker image:
docker:latest(imagen som används som standard)
”Runner registered successfully.” När det meddelandet dyker upp är anställningen klar! Uppdaterar du nu GitLab-skärmen ser du runnern med en grön lampa som ropar ”Redo (Online)”.

Steg 4: pipelinen igång!
I samma stund som runnern registreras börjar den tidigare stillastående (Pending) pipelinen automatiskt röra på sig. Running… och en stund senare Passed!
Jag gjorde absolut ingenting, men maskinen körde testerna, byggde, skapade imagen och laddade upp den i registret helt själv. Jag öppnade terminalen för att kolla loggarna och såg att allt blivit gjort både snabbare och mer prickfritt än när jag hade gjort det manuellt.
”Wow… det funkar verkligen?”
Den manuella deployen som tog 10 minuter avslutas nu med ett enda git push. Nu kan jag dra igång deployen och gå och hämta kaffe.
Praktiskt tips: Docker-rättighetsproblem (Permission Denied)
Det finns ett fel som man stöter på i 99% av fallen när man sätter upp en runner första gången: dial unix /var/run/docker.sock: connect: permission denied
Det är ett problem som beror på att runnern försöker köra Docker-kommandon men saknar rättigheter. Då måste du öppna konfigurationsfilen för gitlab-runner (config.toml) och slå på alternativet privileged = true.
# /etc/gitlab-runner/config.toml (runner-konfigurationsfil)
[[runners]]
name = "my-runner-01"
executor = "docker"
[runners.docker]
privileged = true # Den här raden måste ändras till true för att Docker-in-Docker ska fungera ordentligt. # …
Avslutningsvis: nu kan jag gå hem
Äntligen har jag fått min egen ’deploy-robot’. Nu kan jag fokusera på att bara skriva kod. Det tråkiga och repetitiva valideringen och deployen sköter min trogna robot (Runner) åt mig.
Men det fattas fortfarande 2 %. Just nu körs pipelinen ovillkorligt varje gång det pushas till master-branchen. ”Tänk om jag vill deploya automatiskt till utvecklingsservern (dev), men bara deploya till produktionsservern (prod) när jag själv tryckt på ’godkänn-knappen’?”
Nästa gång ska vi titta på ’deploy-strategi per bransch’ och ’manuellt godkännande (Manual)’ för att styra pipelinen ännu smartare.


