GitLab Runner: Docker atvaizdžių kūrimas

Efektyviai kurkite ir įkelkite Docker atvaizdžius iš savo GitLab CI/CD procesų naudodami Stackhero runner'ius ir Docker-in-Docker

👋 Sveiki atvykę į Stackhero dokumentaciją!

Stackhero siūlo paprastą GitLab Runner cloud sprendimą, kuris leidžia efektyviai ir be rūpesčių vykdyti jūsų GitLab CI/CD užduotis. Štai ko galite tikėtis:

  • Neribotos CI/CD minutės: vykdykite savo pipelines tiek kartų, kiek reikia, be apmokestinimo už minutes ar netikėtų mokesčių.
  • Keli vienu metu vykdomi darbai: spartinkite kūrimo procesą paleisdami kelias užduotis lygiagrečiai.
  • Docker executor su Docker-in-Docker palaikymu: lengvai kurkite ir talpinkite konteinerių atvaizdus kaip CI/CD proceso dalį.
  • Puikiai veikia tiek su GitLab.com, tiek su self-managed GitLab instancijomis.
  • Privati, dedikuota infrastruktūra su greitu NVMe/SSD saugojimu užtikrina stabilų ir nuspėjamą build našumą.
  • Pasiekiama 🇪🇺 Europoje ir 🇺🇸 JAV regionuose, kad atitiktų jūsų komandos poreikius.

Taupykite laiką: galite prijungti savo pirmąjį GitLab Runner ir pradėti vykdyti pipelines vos per kelias minutes!

Naudojant Stackhero GitLab Runner, kiekvienas darbas vykdomas izoliuotame konteineryje su Docker executor. Galite kurti savo Docker atvaizdžius tiesiogiai pipeline'e įjungę Docker-in-Docker (DinD). Ši konfigūracija paleidžia Docker daemon'ą šalia jūsų darbo, todėl CI/CD proceso metu galite naudoti docker build ir docker push komandas.

Kiekvienas paleidimas turi neribotą CI/CD minučių kiekį: galite kurti tiek kartų, kiek reikia, nesirūpindami naudojimo apribojimais. Jūsų build cache saugomas runner'io dedikuotame diske, todėl pakartotiniai build'ai gali naudoti ankstesnius sluoksnius. Tai žymiai sumažina build laiką ir pagreitina pipeline'ų vykdymą.

Į savo repozitoriją galite pridėti šį .gitlab-ci.yml pavyzdį. Ši konfigūracija kuria Dockerfile, esantį jūsų projekto šaknyje:

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:
    # Pakeiskite "my-image" norimu pavadinimu:
    - docker build -t my-image .
    # Papildomai, galite greitai patikrinti sukurtą atvaizdį:
    # - docker run --rm my-image /path/to/tests

Šiame pavyzdyje naudojame Docker atvaizdžio 29 versiją. Galite naudoti naujesnę versiją, kai tik ji pasirodo. Naujausius žymenis rasite oficialiame Docker atvaizdžių puslapyje.

Šioje konfigūracijoje docker:29-dind servisas paleidžia Docker daemon'ą šalia jūsų darbo, o DOCKER_HOST: "tcp://docker:2375" nurodo docker CLI naudoti būtent jį. Visada nustatykite DOCKER_HOST, kai deklaruojate docker:dind servisą: priešingu atveju CLI tyliai prisijungs prie kito daemon'o, todėl build'as gali praeiti net jei servisas sukonfigūruotas neteisingai, kas paslepia tikras problemas (ir sugadina tokius įrankius kaip Testcontainers, kurie priklauso nuo šio serviso). DOCKER_TLS_CERTDIR: "" leidžia jungtis per paprastą, nešifruotą 2375 prievadą vidiniame darbo tinkle.

Kaip paprastesnę alternatyvą, galite praleisti services bloką ir abi kintamąsias: Stackhero runner'is taip pat pateikia paruoštą naudoti Docker daemon'ą per prijungtą socket'ą, todėl paprastas docker build veikia be papildomos konfigūracijos.

Testcontainers yra testavimo biblioteka, prieinama Java, Go, Node.js, Python, .NET ir kitoms kalboms, kuri paleidžia tikras paslaugas kaip laikinas Docker konteinerius jūsų testų metu. Vietoj to, kad imituotumėte duomenų bazę ar žinučių tarpininką, jūsų integraciniai testai bendrauja su tikru PostgreSQL, MySQL, Redis ar Kafka egzemplioriumi, kuris sukuriamas prieš testus ir pašalinamas iškart po jų. Ši biblioteka ypač populiari Java ir Spring projektuose.

Testcontainers reikia Docker daemon'o, todėl jis veikia su ta pačia Docker-in-Docker konfigūracija kaip ir anksčiau. Papildomų kintamųjų nereikia:

test:
  stage: test
  # Naudokite atvaizdį, kurio reikia jūsų testams (čia JDK), nebūtinai docker atvaizdį:
  image: gradle:jdk21
  services:
    - name: docker:29-dind
      alias: docker
  variables:
    DOCKER_HOST: "tcp://docker:2375"
    DOCKER_TLS_CERTDIR: ""
  script:
    - gradle test

Testcontainers naudoja DOCKER_HOST, kad rastų daemon'ą, ir naudoja tą patį docker hostname, kad pasiektų konteinerių publikuotus portus. Abu variantai veikia, nes docker alias'as išsprendžiamas jūsų darbo tinkle.

Palikite DOCKER_HOST savo Testcontainers darbuose. Jei jo nėra, Testcontainers naudoja runner'io prijungtą Docker socket'ą, tada bando pasiekti testų konteinerius per host'o IP adresą, prie kurio jūsų darbas negali prisijungti. Dažniausias simptomas – Ryuk pagalbinio konteinerio klaida Wait strategy failed. Container is removed arba Timed out waiting for log output matching '.*Started.*'.

GitLab pateikia iš anksto apibrėžtus kintamuosius (CI_REGISTRY, CI_REGISTRY_USER, CI_REGISTRY_PASSWORD, CI_REGISTRY_IMAGE), kad jūsų pipeline galėtų saugiai autentifikuotis ir įkelti atvaizdžius į projekto konteinerių registrą. Papildomų slaptažodžių nereikia.

Štai pavyzdinis darbas, kuris sukuria ir įkelia jūsų atvaizdį:

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"
    # Jei esate numatytoje šakoje, galite taip pat pažymėti ir įkelti "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

Norėdami įkelti atvaizdžius į kitą registrą (pvz., Docker Hub ar privatų registrą), galite saugoti prisijungimo duomenis kaip CI/CD kintamuosius ir naudoti juos su docker login tokiu pačiu principu.

Jūsų runner'io diskas išlieka tarp pipeline'ų, todėl galite pakartotinai naudoti atvaizdžių sluoksnius kaip build cache. Tai leidžia pakartotinius build'us atlikti daug greičiau. Štai pavyzdinė konfigūracija:

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:
    # Atsisiųskite naujausią atvaizdį cache'ui (jei yra):
    - 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"

Šis metodas leidžia build'ams naudoti Docker sluoksnių cache, todėl perkurti reikia tik naujus ar pakeistus sluoksnius.

Jūsų planas nurodo, kiek darbų gali būti vykdoma vienu metu. Tos pačios stadijos darbai pradedami kartu, iki jūsų nustatyto lygiagretumo limito. Tai reiškia, kad keli nepriklausomi darbai gali būti vykdomi lygiagrečiai ir baigsis, kai tik lėčiausias darbas bus užbaigtas, nereikia laukti kiekvieno darbo paeiliui.

Pavyzdys:

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

Jei nustatysite lygiagretumą 1 ar didesnį, unit, integration ir e2e darbai bus vykdomi vienu metu.

Daugiau informacijos apie Docker atvaizdžių kūrimą GitLab CI/CD pipeline'uose rasite oficialioje GitLab dokumentacijoje apie Docker build'us.