CI for frontend: Gitlab, Traefik, Docker
The purpose of this article is to show a simple technique of setting up a stand for several branches. This article is written by developers from the developer, so it is unlikely to be of significant interest to professional DevOps engineers.
Requirements:
- Gitlab (bare metal / cloud)
- Dedicated server
- Free domain
Step One: Configure Gitlab
- Install Gitlab Runner on your dedicated server
- Create a docker that supports docker builds of images
- Turn on Container Registry
Step Two: Server Setup
- Install Docker
- Install Compose
- Create a user:
# создаем пользователя для деплоя образов, разрешаем ему работу с докером $ 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 - Configure traefik (server proxying requests to Docker containers based on their labels (labels)):
$ sudo mkdir -p /opt/traefik $ docker network create web # файлы настроек docker-compose & traefik упрощены до предела и должны быть достаточно понятными
/opt/traefik/docker-compose.ymlversion: '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
Replace DOMAIN.COM with your domain.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 - Run traefik:
cd /opt/traefik && docker-compose up -d - Add an entry for DOMAIN.COM of the form '*' - IP of the dedicated server.
Step three: prepare the repository
- Add the Dockerfile to the root of the repository:
FROM node:8.9as 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;"]
Changenpm run build
on your build team. Similarly edit the path/usr/src/app/dist
changing dist to your build directory.
You can read more about the structure and commands of Docherfaye here . - Add the .gitlab-ci.yml file with the image assembly section:
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 - Add the private key [email protected] to the repository settings (Settings -> CI / CD -> Variables) as SSH_PRIVATE_KEY
- Add deploy sections:
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 deployer@DOMAIN.COM "docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN$GITLAB_DOMAIN" - ssh deployer@DOMAIN.COM "docker stop frontend_${CI_COMMIT_REF_SLUG}" || true - ssh deployer@DOMAIN.COM "docker rm frontend_${CI_COMMIT_REF_SLUG}" || true - ssh deployer@DOMAIN.COM "docker rmi GITLAB-DOMAIN.COM/frontend/main/image:${CI_COMMIT_REF_SLUG}" || true - ssh deployer@DOMAIN.COM "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 deployer@DOMAIN.COM "docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN GITLAB-DOMAIN.COM" - ssh deployer@DOMAIN.COM "docker stop frontend_${CI_COMMIT_REF_SLUG}" || true - ssh deployer@DOMAIN.COM "docker rm frontend_${CI_COMMIT_REF_SLUG}" || true - ssh deployer@DOMAIN.COM "docker rmi $GITLAB_DOMAIN/frontend/main/image:${CI_COMMIT_REF_SLUG}" || truewhen: manual environment: name: review/$CI_COMMIT_REF_NAME action: stop
The above steps are enough to get the following result:
- Each new commit into a branch initiates the assembly and development of the latest actual code at% branch_name% .tests.DOMAIN.COM
- Gitlab includes an environment mechanism that allows you to create / delete / open closed images in a couple of touches.
Next steps:
- Set up a separate section for the wizard builds. In the case of the master, it is reasonable to tag the image via COMMIT_SHA
- Add configs to nginx in docker
- To forward the build parameters of the bundle through the ARG and ENV mechanisms of the dockfile
- Configure use of cache from image for assemblies
Based on the article.