GitLab Runner: Budowanie obrazów Docker
Buduj i wysyłaj obrazy Docker bezpośrednio z pipeline’ów GitLab CI/CD, korzystając z własnego Stackhero runnera i Docker-in-Docker
👋 Witamy w dokumentacji Stackhero!
Stackhero oferuje łatwe w użyciu rozwiązanie GitLab Runner cloud, zaprojektowane do wydajnej obsługi zadań GitLab CI/CD. Oto, czego możesz się spodziewać:
- Nielimitowane minuty CI/CD: brak rozliczania za minuty, więc Twoje pipeline'y mogą działać zawsze, gdy tego potrzebujesz.
- Wiele równoczesnych zadań: uruchamiaj kilka jobów jednocześnie, aby przyspieszyć cały pipeline.
- Docker executor z obsługą Docker-in-Docker: usprawnij budowanie i wysyłanie swoich obrazów kontenerów.
- Kompatybilny zarówno z GitLab.com, jak i każdą samodzielnie zarządzaną instancją GitLab.
- Prywatna, dedykowana maszyna wirtualna (VM) oparta na szybkich dyskach NVMe/SSD, zapewniająca stabilne i niezawodne buildy.
- Dostępny w regionach 🇪🇺 Europa oraz 🇺🇸 USA.
Oszczędzaj czas: możesz podłączyć swojego pierwszego GitLab Runnera i uruchomić pipeline'y w zaledwie kilka minut!
Wprowadzenie
Kiedy korzystasz z Stackhero GitLab Runnera, zadania są uruchamiane z użyciem Docker executor. Oznacza to, że każde zadanie startuje w nowym kontenerze, bazującym na wskazanym przez Ciebie image. Jeśli chcesz budować własne obrazy Docker w ramach pipeline’u, możesz skorzystać z Docker-in-Docker (DinD). Taka konfiguracja pozwala na uruchomienie demona Docker równolegle z Twoim zadaniem, dzięki czemu możesz wykonywać polecenia takie jak docker build i docker push bezpośrednio w pipeline’ie.
Jedną z głównych zalet tego rozwiązania jest to, że Twój runner posiada nielimitowane minuty CI/CD. Możesz budować obrazy tak często, jak tylko potrzebujesz. Dodatkowo, ponieważ cache buildów znajduje się na dedykowanym dysku runnera, kolejne budowy mogą wykorzystywać poprzednie warstwy, co znacząco przyspiesza działanie pipeline’ów.
Budowanie obrazu Docker z Docker-in-Docker
Poniżej znajdziesz przykładowy plik .gitlab-ci.yml, który możesz dodać do swojego repozytorium. Ta konfiguracja buduje Dockerfile znajdujący się w katalogu głównym projektu:
build-image:
stage: build
image: docker:27
services:
- docker:27-dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
before_script:
- docker info
script:
# Zamień "my-image" na wybraną nazwę:
- docker build -t my-image .
# Opcjonalnie możesz uruchomić szybki test na zbudowanym obrazie:
# - docker run --rm my-image /path/to/tests
W tej konfiguracji serwis docker:27-dind uruchamia demona Docker. Zmienna DOCKER_TLS_CERTDIR: "/certs" umożliwia bezpieczne połączenie TLS pomiędzy zadaniem a demonem Docker.
Wysyłanie do rejestru kontenerów GitLab
GitLab udostępnia kilka predefiniowanych zmiennych (CI_REGISTRY, CI_REGISTRY_USER, CI_REGISTRY_PASSWORD, CI_REGISTRY_IMAGE), dzięki którym pipeline może zalogować się i wysłać obrazy do rejestru kontenerów projektu bez konieczności podawania dodatkowych sekretów.
Oto przykładowe zadanie, które buduje i wysyła Twój obraz:
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"
# Jeśli jesteś na domyślnej gałęzi, możesz również oznaczyć i wysłać "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
Jeśli chcesz wysyłać obrazy do innego rejestru (np. Docker Hub lub prywatnego rejestru), możesz przechowywać te dane uwierzytelniające jako zmienne CI/CD i używać ich z docker login w podobny sposób.
Przyspieszanie powtarzających się buildów
Ponieważ dysk runnera jest trwały pomiędzy pipeline’ami, możesz przyspieszyć budowanie, wykorzystując poprzednie warstwy obrazu jako cache. Oto jak można to skonfigurować:
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:
# Spróbuj pobrać najnowszy obraz, aby zasilić cache (nie szkodzi, jeśli jeszcze nie istnieje):
- 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"
Takie podejście pozwala Twoim pipeline’om z czasem działać coraz szybciej, dzięki efektywnemu wykorzystaniu cache warstw Docker.
Uruchamianie zadań równolegle
Twój plan określa, ile zadań może być uruchamianych jednocześnie. Zadania w tej samej fazie (stage) startują równolegle, do limitu współbieżności. Oznacza to, że faza z wieloma niezależnymi zadaniami zakończy się, gdy najwolniejsze z nich się skończy, zamiast uruchamiać wszystkie zadania po kolei.
Oto prosty przykład:
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
Jeśli ustawisz współbieżność na 3 lub więcej, zadania unit, integration i e2e zostaną uruchomione jednocześnie.
Jeśli chcesz dowiedzieć się więcej o budowaniu obrazów Docker w CI, zapoznaj się z oficjalną dokumentacją GitLab.