GitLab
Основные функции GitLab
- Система контроля версий
- Система построения CI/CD
- Встроенный Docker Registry
Схема CI/CD процессов
![[media/CI-CD-scheme.png]]
Continuous Delivery могут называть также CDL, а Continuous Deployment - CDP.
Pipeline
Пример пайплайна сборки docker образа после тестов:
![[media/docker-build-after-tests-pipeline.png]]
Как сохранять состояния между job-ами: Caching in GitLab CI/CD
Ручной запуск job-а
Задачи по типу docker build
не всегда нужно повторять. Банально, не всегда есть смысл заново собирать образ, который уже собран и ждем в Container Registry.
Поэтому такие задачи можно оставить на ручной запуск в gitlab-ci.yml
:
script:
- echo test
when: manual
Predefined CI/CD variables
Предопределенные переменные генерируются при запуске пайплайна в рамках этого пайплайна и каждого job-а.
Сервисы
Сервис - это дополнительный контейнер, поднимающийся вместе с основным в момент выполнения задачи.
Серсивы имеют доступ к переменным.
Сервисы можно конфигурировать:
services:
- name: custom-postgres:11.7
alias: shmostgress
entrypoint: ["/usr/local/bin/db-postgres"]
command: ["start"]
Можно юзать разные версии одного сервиса, например, для тестирования.
docker:dind
или "Docker in Docker"
Образ docker:dind
(dind
- docker in docker) нужен, если хочешь работать с docker
и его командами, но не в хостовой системе.
dind
share-ит свой сокет наружу, что позволяет, юзать командыdocker
из других контейнеров.
Самый частый use case - сборка образов, каждый из которых сохраняется локально и если каждый образ собирать на хостовой системе - там просто кончится место на диске, потому что образы заполнят всё. Поэтому берется контейнер с docker-ом, внутри которого уже собирается образ, который сохранится в рамках этого контейнера.
Вызывается как сервис:
...
services:
- docker:dind
...
GitLab Container Registry
Контейнеры это stateless и immutable инфраструктура:
+ stateless: контейнеры не сохраняют состояние между запусками (в этом же и идея docker-а, что все данные должны быть внешними / в виде volume-ов).
+ immutable: контейнеры неизменяемы после создания, то есть, для обновлений создаются новые образы, а старые удаляются.
Это к тому, что всё, что произошло внутри контейнера будет потеряно, когда контейнер выключится. То есть, образ, собранный внутри контейнера, не сохранится никак в системе после выключения этого контейнера.
Поэтому нужен какой-нибудь Container Registry 👇.
GitLab Container Registry - доп. функция GitLab-а, позволяющая хранить docker-образы для проектов.
- Для каждого проекта - свой реестр
- Доступ по учетке в GitLab
- Доступ через CI по токену
Для того, чтобы собрать и запушить образ в GitLab Container Registry нужно:
1. docker login
2. docker build
3. docker push
Docker build:
stage: build
image: docker:stable
services:
- docker:dind
script:
- docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}
- docker build -t ${CI_REGISTRY}/${CI_PROJECT_PATH}/${CI_PROJECT_NAME}:${CI_COMMIT_REF_SLUG} .
- docker push ${CI_REGISTRY}/${CI_PROJECT_PATH}/${CI_PROJECT_NAME}:${CI_COMMIT_REF_SLUG}
- docker tag ${CI_REGISTRY}/${CI_PROJECT_PATH}/${CI_PROJECT_NAME}:${CI_COMMIT_REF_SLUG} ${CI_REGISTRY}/${CI_PROJECT_PATH}/${CI_PROJECT_NAME}:latest
- docker push ${CI_REGISTRY}/${CI_PROJECT_PATH}/${CI_PROJECT_NAME}:latest
tags:
- docker
login
docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}
логин, где gitlab-ci-token
- автоматически созданный юзер для тебя с такими же правами, как у тебя.
build и push
docker build -t ${CI_REGISTRY}/${CI_PROJECT_PATH}/${CI_PROJECT_NAME}:${CI_COMMIT_REF_SLUG} .
docker push ${CI_REGISTRY}/${CI_PROJECT_PATH}/${CI_PROJECT_NAME}:${CI_COMMIT_REF_SLUG}
Используются GitLab CI predefined variables, чтобы собрать и запушить образ, который после этого будет доступен по подобной ссылке: registry.gitlab.com/arut-plus/docker-cicd-django/docker-cicd-django:master
.
Но нужен образ с тегом latest
, поэтому следующий шаг это реализует.
tag и push
docker tag ${CI_REGISTRY}/${CI_PROJECT_PATH}/${CI_PROJECT_NAME}:${CI_COMMIT_REF_SLUG} ${CI_REGISTRY}/${CI_PROJECT_PATH}/${CI_PROJECT_NAME}:latest
docker push ${CI_REGISTRY}/${CI_PROJECT_PATH}/${CI_PROJECT_NAME}:latest
Заново тегируется образ и опять пушится. В итоге в registry запушится один образ с двумя тегами.
В итоге, можно будет юзать ссылку на образ с тегом latest
: registry.gitlab.com/arut-plus/docker-cicd-django/docker-cicd-django:latest
Ссылку на образ можно скопировать в Deploy > Container Registry.
В docker-compose.yml
это будет выглядеть, например, так:
services:
web:
image: registry.gitlab.com/arut-plus/docker-cicd-django/docker-cicd-django:latest
При чем, при деплое, а конкретнее, до
docker-compose
, можно заменить latest на имя ветки такой командой:
Bash- sed s/:latest/:${CI_COMMIT_REF_SLUG}/g -i ./docker-compose.yml - docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY} - docker-compose pull ...
after_script
не останавливает пайплайн
Ошибка при выполнении кода в блоке after_script
не пометит пайплайн как failed
. Это такое исключение, которое отличает after_script
от before_script
и script
.
Сохранение результатов в пайплайне
Cache
Используется для сохранения результата между задачами в рамках этапа.
За cache отвечает runner.
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .npm/
key
нужен для обращения к кешу.
В тестах может понадобится еще одна конфигурация:
some test:
artifacts:
when: on_failure
Artifacts
Используется для передачи состояния между этапами.
Артефакты можно скачать прямо в GitLab WebUI - поэтому их и юзают для получения, например, тест-репортов или apk-пакетов.
Артефакты сохраняет GitLab - runner здесь не при чем, ибо это зона ответственности самой платформы (GitLab).
pdf:
script: xelatex mycv.tex
artifacts:
paths:
- mycv.pdf
expired_in: 1 week
[[gitlab-runner]]