Как собрать Docker image средствами GitLab CI на примере NuxtJs проекта

К счастью ушло время когда для обновления кода нужно было заходить на сервер, выполнять git pull и запускать миграции вручную. И не будем вспоминать о загрузке кода через FTP/SFTP и т.п…
Благо сейчас почти везде используют docker контейнеры, а с их помощью транспортировать код стало просто.
Следующая ступень в автоматизации деплоя проекта это использовать CI/CD (Continues Integration / Continues Delivery).


На примере проекта на Nuxt.js продемонстрирую как можно использовать GitLab CI/CD для сборки docker image.

У GitLab.com имеется ограничение на размер репозитория в 10 гигабайт, в это ограничение входит и размер registry, а так же 400 минут CI/CD в месяц для бесплатного тарифа.


Создадим проект

Для создания папки с проектом нужно выполнить

yarn create nuxt-app test-ci

Перейдем в папку с проектом

cd test-ci

Можем для проверки запустить, выполнив команду yarn dev и открыть http://127.0.0.1:3000 в своем браузере


Для работы проекта в docker контейнере нужно сменить ip с 127.0.0.1 на 0.0.0.0, иначе не будет доступа к веб-серверу с хост машины.
Нужно в nuxt.config.js после export default { добавить

server: {
  host: '0.0.0.0'
},

Будем использовать переменную GIT_BRANCH, значением будет название ветки для которой происходит сборка.
Применение может быть разным, например: включать счетчик google analytics только для master ветки.

Простой способ использовать эту переменную, это вывесть в заголовок страницы.
Нужно в в nuxt.config.js после head: { добавить

titleTemplate: `%s - ${process.env.GIT_BRANCH || 'local'}`,

Посмотреть файл nuxt.config.js полностью


Создадим файл Dockerfile в корне проекта

FROM node:14-alpine AS node

ARG branch
ENV GIT_BRANCH ${branch}

WORKDIR /var/www
ADD . /var/www

RUN yarn install

EXPOSE 3000
ENTRYPOINT yarn dev

Настройка репозитория в GitLab


Создание Deploy Token

Screenshot 2020-10-27 at 13.59.29.png

Нужно зайти в ваш репозиторий и перейти к настройкам:
Settings -> Repository -> Deploy Tokens
Добавим новый Deploy Token со следующими значениями:
Name: Deployer
Username: Deployer
Scopes: read_repository, read_registry, write_registry
После нажатия кнопки Create deploy token, получим токен


Добавление переменной ACCESS_TOKEN для CI/CD

Screenshot 2020-10-27 at 14.03.04.png

Нужно перейти в настройки:
Settings -> CI / CD -> Variables
Нажать Add Variable

Добавим новую переменную со следующими значениями:
Key: ACCESS_TOKEN
Value: {введите токен полученный ранее}
Нажать кнопку Add variable

Если нужно выполнять сборку для не protected веток, то нужно убрать галочку Protect variable


Теперь нужно вернуться к коду проекта и создать ci config файл .gitlab-ci.yml в корне проекта

stages:
  - build

build-docker:
  stage: build
  image: docker:stable
  only:
    - master
    - develop
  services:
    - docker:dind
  before_script:
    - docker login -u Deployer -p ${ACCESS_TOKEN} registry.gitlab.com
  script:
    - docker build -t ${DOCKER_ENV_CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_NAME} --build-arg branch=${CI_COMMIT_REF_NAME} .
    - docker push ${DOCKER_ENV_CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_NAME}

Значение переменных:
DOCKER_ENV_CI_REGISTRY_IMAGE - путь к registry (registry.gitlab.com/egorvakh/test-ci)
CI_COMMIT_REF_NAME - название текущий ветки
ACCESS_TOKEN - пароль для авторизации в registry

Другие переменные gitlab ci

В данном конфиге указано:

  • Выполнение билда будет только после пуша в ветки master и develop
  • Перед началом скрипта, происходит авторизация в GitLab container registry с помощью юзера Deployer и пароля, который храниться в переменной ACCESS_TOKEN
  • Выполняется команда сборки docker image, в качестве тега будет использоваться название ветки репозитория, а также передаем название ветки в Dockerfile через аргумент branch
  • Загрузка docker image в registry

Добавим git, настроим, запушим код в репозиторий

git init
git remote add origin [email protected]:Egorvakh/test-ci.git` (как пример, поменять ссылку на ваш репозиторий)
git add .
git commit -m "Initial commit"
git push origin master

Если зайти в CI / CD -> Pipelines, увидим запущенную сборку
Screenshot 2020-10-16 at 14.13.53.png

Screenshot 2020-10-16 at 14.14.40.png

После завершения сборки, будет доступен docker image
Screenshot 2020-10-16 at 14.19.32.png


Результат

Запуск контейнера (замените registry.gitlab.com/egorvakh/test-ci на путь к вашему registry)

docker login -u Deployer -p {введите токен полученный ранее} registry.gitlab.com
docker run -it -p 3000:3000 --name test-ci registry.gitlab.com/egorvakh/test-ci:master

Смотрим страницу http://127.0.0.1:3000

В заголовке страницы можно увидеть название ветки репозитория test-ci - master

Screenshot 2020-10-16 at 20.39.05.png

Автоматическая загрузка новой сборки

Для автоматизации процесса деплоя на стороне сервера можно использовать watchtower.
Watchtower поможет с мониторингом свежих docker image, а при их наличии запускает процесс загрузки и перезапуска контейнера, но уже на свежем образе.

Пример использования: (замените registry.gitlab.com/egorvakh/test-ci:master на путь к вашему registry)

docker login -u Deployer -p {введите токен полученный ранее} registry.gitlab.com
docker run -it -p 3000:3000 --name test-ci registry.gitlab.com/egorvakh/test-ci:master
docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower test-ci --interval 60

Код доступен в GitLab