▍CI/CD в GitLab¶
Настройка CI/CD в GitLab для автоматической сборки проекта сайта на MkDocs¶
В нашем случае будет использоваться связка docker контейнеров:
- Traefik
- Gitlab
- Gitlab-runner
- Nginx
Для начала создадим структуру директорий в которых будут храниться конфиги и данные наших контейнеров:
sudo mkdir -p /srv/docker/{conf,data/www}
Описывать параметры контейнеров будем в файле /srv/docker/docker-compose.yml.
Настройка Traefik¶
# Пропишем версию
version: '3.3'
# Перечислим сервисы
services:
traefik:
image: traefik:latest
container_name: traefik
restart: always
security_opt:
- no-new-privileges:true
ports:
- 192.168.0.111:80:80
- 192.168.0.111:443:443/tcp
- 192.168.0.111:443:443/udp
environment:
- SELECTEL_API_TOKEN=345645456wefgsdg76dg8dg7d78g67dfg
volumes:
- $DIR_CONF/traefik/traefik.yml:/traefik.yml:ro
- $DIR_CONF/traefik/acme.json:/acme.json
- $DIR_CONF/traefik/config.yml:/config.yml:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /etc/localtime:/etc/localtime:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.routers.traefik.rule=Host(`traefik.example.ru`)"
- "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
- "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
- "traefik.http.middlewares.traefik-auth.basicauth.users=username:$$apr1$$QDKFN7LI$$iz.jL7bGBJCEygQDKQdUC0"
- "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
- "traefik.http.routers.traefik-secure.entrypoints=https"
- "traefik.http.routers.traefik-secure.rule=Host(`traefik.example.ru`)"
- "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare"
- "traefik.http.routers.traefik-secure.tls.domains[0].main=example.ru"
- "traefik.http.routers.traefik-secure.tls.domains[0].sans=*.example.ru"
- "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.excludedips=172.18.0.0/24"
- "traefik.http.middlewares.WhitelistHome.ipwhitelist.sourcerange=172.18.0.0/24, 192.168.0.0/16"
- "[email protected]"
В моём случае настройка DNS записей производится через API Selectel. Чтобы задать параметр SELECTEL_API_TOKEN нужно перейти на страницу Ключи API, нажав на Новый ключ.
Для дополнительной защиты админки используется парольная авторизация, это параметр:
"traefik.http.middlewares.traefik-auth.basicauth.users=username:$$apr1$$QDKFN7LI$$iz.jL7bGBJCEygQDKQdUC0"
Где в качестве логина испльзуется username, а пароль: test12345 Для генерации этой пары воспользуйтесь командой:
Также настроен белый список для доступа к админке, это параметр:
Для поддержки HTTP/3 необходимо указать как TCP так и UDP для 443 порта, также не забыть открыть их на фаерволе.
http:
routers:
kibana:
entryPoints:
- "https"
rule: "Host(`kibana.example.ru`)"
middlewares:
- WhitelistHome
tls: {}
service: kibana
services:
kibana:
loadBalancer:
servers:
- url: "http://192.168.0.10:5601"
passHostHeader: true
middlewares:
default-headers:
headers:
frameDeny: true
sslRedirect: true
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 31536000
customFrameOptionsValue: SAMEORIGIN
customRequestHeaders:
X-Forwarded-Proto: https
customResponseHeaders:
server: Blackbox
x-powered-by: Blackbox
referrerpolicy: same-origin
#contentSecurityPolicy: script-src 'self'
permissionsPolicy: geolocation=(self), microphone=(), camera=()
WhitelistHome:
ipWhiteList:
sourceRange:
- "10.0.0.0/8"
- "192.168.0.0/16"
- "172.16.0.0/12"
secured:
chain:
middlewares:
- default-whitelist
- default-headers
tls:
options:
default:
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 # TLS 1.2
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 # TLS 1.2
- TLS_AES_256_GCM_SHA384 # TLS 1.3
- TLS_CHACHA20_POLY1305_SHA256 # TLS 1.3
curvePreferences:
- CurveP521
- CurveP384
minVersion: VersionTLS12
sniStrict: true
mintls13:
minVersion: VersionTLS13
api:
dashboard: true
debug: true
experimental:
http3: true
entryPoints:
http:
address: ":80"
http:
redirections:
entrypoint:
to: https
scheme: https
permanent: true
https:
address: ":443"
forwardedHeaders:
trustedIPs:
- "127.0.0.1/32"
- "10.0.0.0/8"
- "192.168.0.0/16"
- "172.16.0.0/12"
http3: {}
serversTransport:
insecureSkipVerify: true
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
filename: /config.yml
watch: true
certificatesResolvers:
selectel:
acme:
email: [email protected]
storage: acme.json
dnsChallenge:
provider: selectel
delayBeforeCheck: 10
resolvers:
- "188.68.203.5:53"
- "77.223.114.10:53"
- "188.68.203.10:53"
- "77.223.114.5:53"
- "1.1.1.1:53"
- "8.8.8.8:53"
В файле /srv/docker/.env пропишем пути:
Теперь можно и запустить контейнер:
Настройка Gitlab¶
version: '3.3'
services:
gitlab:
image: gitlab/gitlab-ce:latest
container_name: gitlab
restart: always
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'https://gitlab.example.ru'
nginx['listen_port'] = 80
nginx['listen_https'] = false
nginx['proxy_set_headers'] = {
"X-Forwarded-Proto" => "https",
"X-Forwarded-Ssl" => "on"
}
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.mail.ru"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "maillogin"
gitlab_rails['smtp_password'] = "mailpassword"
gitlab_rails['smtp_domain'] = "mail.ru"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = false
gitlab_rails['smtp_tls'] = true
gitlab_rails['smtp_openssl_verify_mode'] = 'peer'
gitlab_rails['gitlab_email_from'] = 'maillogin'
gitlab_rails['gitlab_email_reply_to'] = 'maillogin'
shm_size: '256m'
volumes:
- $DIR_CONF/gitlab:/etc/gitlab
- $DIR_DATA/gitlab:/var/opt/gitlab
- /etc/localtime:/etc/localtime:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.gitlab.entrypoints=http"
- "traefik.http.routers.gitlab.rule=Host(`gitlab.example.ru`)"
- "traefik.http.middlewares.gitlab-https-redirect.redirectscheme.scheme=https"
- "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
- "traefik.http.routers.gitlab-secure.middlewares=WhitelistHome"
- "traefik.http.routers.gitlab.middlewares=gitlab-https-redirect"
- "traefik.http.routers.gitlab-secure.entrypoints=https"
- "traefik.http.routers.gitlab-secure.rule=Host(`gitlab.example.ru`)"
- "traefik.http.routers.gitlab-secure.tls=true"
- "traefik.http.routers.gitlab-secure.service=gitlab"
- "traefik.http.services.gitlab.loadbalancer.server.port=80"
Если вы используете свой домен подключеyный к VK Work Space, то maillogin указываете целиком - maillogin@example.ru при этом smtp_domain остается mail.ru.
Снова выполняем docker-compose up -d, ждём... долго...
Проверить статус загрузки можно командой:
Периодически пытаемя заходим на gitlab.example.ru. Если удалось, то достаём пароль от панели управления:Соотвественно для авторизации используем логин root и пароль из вывода сверху.
Настройка CI/CD в Gitlab¶
После авторизации в настройках профиля можно будет изменить язык на русский. Создаем новый проект и переходим слева в меню в "Настройки" -> "CI/CD" -> разворачиваем "Runner'ы". Для настройки самого runner нам понадобятся данные URL и токен регистрации.
Добавляем в /srv/docker/docker-compose.yml описание Gitlab-runner:
gitlab-runner:
image: 'gitlab/gitlab-runner:latest'
container_name: gitlab-runner
restart: always
links:
- gitlab
volumes:
- $DIR_CONF/gitlab-runner:/etc/gitlab-runner
- /var/run/docker.sock:/var/run/docker.sock
- /etc/localtime:/etc/localtime:ro
Выполняем docker-compose up -d и запускаем процесс регистрации нашего ранера: Добавляем в /srv/docker/docker-compose.yml описание Gitlab-runner:
[[email protected]:/srv/docker]$ docker exec -ti gitlab-runner gitlab-runner register
Runtime platform arch=amd64 os=linux pid=29 revision=c6bb62f6 version=14.10.0
Running in system-mode.
Enter the GitLab instance URL (for example, https://gitlab.com/):
https://gitlab.example.ru
Enter the registration token:
XMvANz3QF6fFgFsivdsocNsSAp7M1s
Enter a description for the runner:
[ffffffffffff]: blog
Enter tags for the runner (comma-separated):
mkdocs*
Enter optional maintenance note for the runner:
Registering runner... succeeded
Enter an executor: docker, docker-ssh, ssh, docker-ssh+machine, kubernetes, custom, parallels, shell, virtualbox, docker+machine:
docker
Enter the default Docker image (for example, ruby:2.7):
squidfunk/mkdocs-material
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
URL и токен нужно указать такие же как и на странице настроек в панели управления Gitlab. Пункты "Enter an executor" и "Enter the default Docker image" нужно оставить как указано.
Настройка Nginx¶
nginx:
image: nginx:latest
container_name: nginx
restart: always
volumes:
- $DIR_DATA/www:/www
- $DIR_CONF/nginx:/etc/nginx
- /etc/localtime:/etc/localtime:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.nginx.entrypoints=http"
- "traefik.http.routers.nginx.rule=Host(`example.ru`, `www.example.ru`)"
- "traefik.http.middlewares.nginx-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.nginx.middlewares=nginx-https-redirect"
- "traefik.http.routers.nginx-secure.entrypoints=https"
- "traefik.http.routers.nginx-secure.rule=Host(`example.ru`, `www.example.ru`)"
- "traefik.http.routers.nginx-secure.tls=true"
- "traefik.http.routers.nginx-secure.tls.certresolver=http"
- "traefik.http.routers.nginx-secure.service=nginx"
- "traefik.http.services.nginx.loadbalancer.server.port=80"
Выполняем docker-compose up -d, и создаем конфиг нового сайта:
server {
listen 80;
server_name example.ru www.example.ru;
root /www/example.ru/site;
location / {
index index.html;
}
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|pdf|ppt|txt|bmp|rtf|js|woff)$ {
expires 30d;
}
}
Проверяем корректность синтаксиса в конфигах nginx:
docker exec -ti nginx nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Если всё ок, то делаем reload сервера:
Тепеь создадим пустышку сайта, для этого перейдём в директорию /srv/docker/data/www/example.ru и выполним команду:
В результате у нас появятся два файла:
Файл mkdocs.yml — это файл конфигурации, используемый MkDocs. Файлы, находящиеся в папке docs (в частности, index.md) — это исходные материалы, из которых в дальнейшем будет сгенерирован наш сайт.
Генерируем сайт по существующим материалам:
В результате в директории с материалами появилась поддиректория site, в которую генератор записал только что созданный сайт.
Настройка репозитория¶
Теперь настроим Gitlab CI и Gitlab Runner для генерации статического сайта. Для этого нам понадобиться добавить наш сайт в систему контроля версии и создать файл .gitlab-ci.yml, который будет автоматически собирать наш сайт после сохранения новых изменений.
- Перейдём в директорию /srv/docker/data/www/example.ru
- Создадим файл .gitignore и внесём в него 1 строку (команду игнорировать папку site); для этого в терминале введём команду
- Создадим репозиторий командой
- Создадим первый коммит, состоящий из всех созданных нами файлов Снова вернёмся в панель управления Gitlab, где нужно будет скопировать путь до нашего проекта:
Далее воспользуемся этой ссылкой для сохранения созданного репозитория в созданный проект gitlab:
Теперь, когда репозиторий создан и связан с Gitlab, создадим в папке с исходными материалами файл .gitlab-ci.yml:
stages:
- build
- deploy
build_docs_job:
stage: build
tags: [mkdocs]
only:
- /^master$/
- merge_requests
image:
name: squidfunk/mkdocs-material
entrypoint: [""]
script:
- 'mkdocs build --site-dir site'
artifacts:
name: "site_$($CI_PIPELINE_IID)"
paths:
- site
deploy:
stage: deploy
tags: [mkdocs]
image:
name: squidfunk/mkdocs-material
entrypoint: [""]
dependencies:
- build_docs_job
only:
- /^master$/
before_script:
- (if [ -d "site" ]; then echo ok; else exit "no build folder, try to run pipeline again"; fi);
script:
- cp -r site/* /site/
Чтобы сработал deploy и были скопированы файлы при работе команды:
нужно прокинуть папку /srv/data/www/example.ru/site внуть docker контейнера squidfunk/mkdocs-material, который будет запускаться ранером в процессе сборки. Для этого отредактируем файл:где параметр:
volumes = ["/cache"]
заменить на:
volumes = ["/cache", "/srv/docker/data/www/example.ru/site:/site"]
Этим файлом мы указали Gitlab CI собирать сайт каждый раз, когда появляются новые коммиты в ветке master или в процессе создания или обновления merge request-ов.
Настройка почтовых уведомлений через SMTP¶
Для проверки корректности работы SMTP зайдём в консоль контейнера:
Далее заходим в консоль гита:и выполняем отправку тестового письма:
Notify.test_email('[email protected]', 'zagolovok_gitlab email', 'Test_mail').deliver_now
Ошибки и их решения¶
Развернуть
*** Пожалуйста, скажите мне кто вы есть.
Запустите
git config --global user.email "[email protected]"
git config --global user.name "Ваше Имя"
для указания идентификационных данных аккаунта по умолчанию.
Пропустите параметр --global для указания данных только для этого репозитория.