В каждом уважающем себя проекте должны участвовать QA инженеры. Ежедневно перед ними будет стоять задача проверки выполнения задач в отдельных ветках. Очень часто процесс перехода на нужную ветку, сборки и тестирования занимает много времени, к тому же, локально не всегда возможно полностью воссоздать максимально идентичное боевому окружение.
Цель данной статьи — показать простую технику настройки стенда на несколько веток. Данная статья написана разработчикам от разработчика, поэтому вряд ли будет представлять существенный интерес для профессиональных DevOps инженеров.
Требования:
- Gitlab (bare metal/cloud)
- Выделенный сервер
- Свободный домен
Шаг первый: настройка Gitlab
- Установите Gitlab Runner на Вашем выделенном сервере
- Создайте воркера, поддерживающего сборки docker образов
- Включите Container Registry
Шаг второй: настройка сервера
- Установите Docker
- Установите Compose
- Создайте пользователя:
# создаем пользователя для деплоя образов, разрешаем ему работу с докером $ sudo adduser deployer $ sudo groupadd docker $ sudo usermod -aG docker deployer # генерим ssh ключи $ su deployer $ ssh-keygen -t rsa (when asked for a passphrase, enter no passphrase) # разрешаем подключение к серверу с только что созданным ключом $ cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys
- Настройте traefik (сервер, проксирующий запросы к Docker контейнерам на базе их ярлыков(лейблов)):
$ sudo mkdir -p /opt/traefik $ docker network create web # файлы настроек docker-compose & traefik упрощены до предела и должны быть достаточно понятными
/opt/traefik/docker-compose.yml
version: '2' services: traefik: image: traefik:1.4.6 restart: always ports: - 80:80 networks: - web volumes: - /var/run/docker.sock:/var/run/docker.sock - ./traefik.toml:/traefik.toml container_name: traefik networks: web: external: true
/opt/traefik/traefik.toml
Замените DOMAIN.COM на свой домен.debug = true checkNewVersion = true logLevel = "ERROR" defaultEntryPoints = ["http"] [entryPoints] [entryPoints.http] address = ":80" [retry] [docker] endpoint = "unix:///var/run/docker.sock" domain = "DOMAIN.COM" watch = true exposedbydefault = false
- Запустите traefik:
cd /opt/traefik && docker-compose up -d
- Добавьте A запись для DOMAIN.COM вида ‘*’ — IP выделенного сервера.
Шаг третий: подготовка репозитория
- Добавьте в корень репозитория Dockerfile:
FROM node:8.9 as build-deps WORKDIR /usr/src/app COPY package.json ./ RUN npm i COPY . ./ RUN npm run build FROM nginx:1.12-alpine COPY --from=build-deps /usr/src/app/dist /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
Измените
npm run build
на вашу команду сборки. Аналогично отредактируйте путь
/usr/src/app/dist
изменив dist на вашу директорию сборки.
Подробнее почитать про структуру и команды докерфайа можно тут. - Добавьте .gitlab-ci.yml файл с секцией сборки образа:
image: docker:stable variables: DOCKER_HOST: tcp://docker:2375/ DOCKER_DRIVER: overlay2 GITLAB_DOMAIN: gitlab.com services: - docker:dind stages: - build build_staging: stage: build script: - export GITLAB_DOMAIN=gitlab.com - export CONTAINER_IMAGE=$GITLAB_DOMAIN/frontend/main/image - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $GITLAB_DOMAIN - docker pull $CONTAINER_IMAGE:$CI_COMMIT_REF_SLUG || true - export URL="Host:${CI_COMMIT_REF_NAME}.tests.DOMAIN.COM" - docker build -t $CONTAINER_IMAGE:$CI_COMMIT_REF_SLUG . --label "traefik.backend=${CI_COMMIT_REF_NAME}" --label "traefik.frontend.rule=${URL}" - docker push $CONTAINER_IMAGE:$CI_COMMIT_REF_SLUG
- Добавьте приватный ключ [email protected] в настройки репозитория(Settings -> CI/CD -> Variables) как SSH_PRIVATE_KEY
- Добавьте deploy секции:
stages: - build - deploy /// .... deploy_staging: stage: deploy image: kroniak/ssh-client:3.6 script: - mkdir ~/.ssh - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' - eval $(ssh-agent -s) - ssh-add <(echo "$SSH_PRIVATE_KEY") - ssh [email protected] "docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $GITLAB_DOMAIN" - ssh [email protected] "docker stop frontend_${CI_COMMIT_REF_SLUG}" || true - ssh [email protected] "docker rm frontend_${CI_COMMIT_REF_SLUG}" || true - ssh [email protected] "docker rmi GITLAB-DOMAIN.COM/frontend/main/image:${CI_COMMIT_REF_SLUG}" || true - ssh [email protected] "docker run --name frontend_${CI_COMMIT_REF_SLUG} --network=web -d $GITLAB_DOMAIN/frontend/main/image:${CI_COMMIT_REF_SLUG}" environment: name: review/$CI_COMMIT_REF_NAME url: http://${CI_COMMIT_REF_NAME}.tests.DOMAIN.COM on_stop: stop_staging stop_staging: stage: deploy image: kroniak/ssh-client:3.6 variables: GIT_STRATEGY: none script: - mkdir ~/.ssh - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' - eval $(ssh-agent -s) - ssh-add <(echo "$SSH_PRIVATE_KEY") - ssh [email protected] "docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN GITLAB-DOMAIN.COM" - ssh [email protected] "docker stop frontend_${CI_COMMIT_REF_SLUG}" || true - ssh [email protected] "docker rm frontend_${CI_COMMIT_REF_SLUG}" || true - ssh [email protected] "docker rmi $GITLAB_DOMAIN/frontend/main/image:${CI_COMMIT_REF_SLUG}" || true when: manual environment: name: review/$CI_COMMIT_REF_NAME action: stop
Приведенных выше шагов достаточно для получения следующего результата:
- Каждый новый коммит в ветку иницирует сборку и развертку последнего актуального кода по адресу %branch_name%.tests.DOMAIN.COM
- В Gitlabе включен механизм окружений, позволяющий в пару касаний создавать/удалять/открывать задеплоенные образы
Следующие шаги:
- Настроить отдельную секцию для сборок мастера. В случае мастера разумно тэгать образ через COMMIT_SHA
- Добавить конфиги к nginxу в докере
- Пробросить параметры сборки бандла через ARG и ENV механизмы докерфайла
- Настроить использование кэша из образа для сборок