从头开始配置Gitlab的CI/CD实现Vue项目自动部署

简述

CI/CD早不是什么新鲜玩意儿了,在公司时有专职运维,给我们配置好了自动化构建和部署。特别是自动化部署,很是方便,但是自己私下的项目也想使用,今天就实践了一下,并把遇到的一些坑记录下来。

Gitlab是一款常用的代码自托管系统,在过去经历的公司中大多采用它。它功能强大易用,但是需要较多系统资源,特别是内存,最好8G以上,本次测试使用的是我本地一台64G内存的Nas。

本次以Vue3项目为例,一步一步实现提交代码到Gitlab之后,自动使用最新代码部署。

原理

原理其实很简单,我们在系统中配置好runner,代码提交后读取项目中的.gitlab-ci.yml文件,根据配置进行构建,并执行部署命令

Gitlab配置

Gitlab和Runner的安装

如今安装软件我一般都使用docker-compose,写好配置文件,可以反复使用,一键安装。

version: "2"
services:
  gitlab:
    image: 'docker.nju.edu.cn/gitlab/gitlab-ce'
    container_name: gitlab1
    restart: unless-stopped
    hostname: 'gitlab'
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'https://gitlab.air.nload.top/'
        gitlab_rails['gitlab_shell_ssh_port'] = 12222
        nginx['listen_port'] = 5000
        nginx['listen_https'] = false
        nginx['redirect_http_to_https'] = false
    ports:
      - '5000:5000'
      - '12222:22'
    volumes:
      - '/data/gitlab/config:/etc/gitlab'
      - '/data/gitlab/logs:/var/log/gitlab'
      - '/data/gitlab/data:/var/opt/gitlab'

  gitlab-runner:
    image: 'docker.nju.edu.cn/gitlab/gitlab-runner'
    container_name: gitlab-runner1
    restart: unless-stopped
    environment:
      GITLAB_URL: 'https://gitlab.air.nload.top/'
      GITLAB_RUNNER_TOKEN: 'glrt-pnnDPdFoM2121X1YxxsB'
      GITLAB_RUNNER_EXECUTOR: 'docker'
      GITLAB_RUNNER_DOCKER_IMAGE: 'docker:latest'
      GITLAB_RUNNER_DOCKER_PRIVILEGED: 'true'
      GITLAB_RUNNER_DOCKER_VOLUMES: '/var/run/docker.sock:/var/run/docker.sock'
    volumes:
      - '/data/gitlab/runner/config:/etc/gitlab-runner'
      - '/var/run/docker.sock:/var/run/docker.sock'

配置文件比较简单,由于墙的原因,国内使用Docker经常遇到网络问题,这里我使用了南京大学的Docker镜像,直接在image名称前加上域名即可。

Gitlab的web我使用了5000端口,前端使用Caddy进行反代和https加密。ssh使用了非22端口,避免和系统冲突。

gitlab-runner相关的配置也可以不写,等系统部署好用另外的方式填上。

然后运行docker-compose up -d,Gitlab启动较慢,稍等片刻就可以在浏览器中打开你配置的网址了。

创建Runner

打开https://gitlab.air.nload.top/admin/runners 这个页面,新建一个Runner,其实没有太多要填的内容,只填一个tags即可,和项目中保持一致即可

image-20231208003734168

创建完毕会出现一行命令,用于Runner的注册,要记下来,因为只会显示一次,我的是

gitlab-runner register  --url https://gitlab.air.nload.top  --token glrt-vxARG_k1jHYqvbyRT4RQ

Runner配置

在第一步,我们的runner已经运行起来了,如果你没有更改容器名称,可以用这个命令进入容器的shell

docker exec -it gitlab-runner1 bash

然后运行上一步得到的命令,会有些提示,让你输入内容,基本默认值就行,image随便填就行,我们在项目里再定义。

如果没有什么意外的话,就注册成功了,也可以在网页管理界面中看到runner的状态。

如果失败了,可能是url问题,确保容器里可以访问到这个url。

成功执行以后,我们打开生成的配置文件编辑一下,这里我是在宿主机编辑的vi /data/gitlab/runner/config/config.toml

concurrent = 1
check_interval = 0
shutdown_timeout = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "b902dbedf3ab"
  url = "https://gitlab.air.nload.top"
  id = 1
  token = "glrt-pnnDPdFoM2121X1YxxsB"
  token_obtained_at = 2023-12-07T15:02:49Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "docker"
  [runners.cache]
    MaxUploadedArchiveSize = 0
  [runners.docker]
    tls_verify = false
    image = "docker.nju.edu.cn/docker:24.0.7"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
    shm_size = 0
    network_mtu = 0

注意有几处修改,privileged = truevolumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"] 特别是volume,刚开始配置好一直报错ERROR: error during connect: Get "http://docker:2375/_ping": dial tcp: lookup docker on 223.5.5.5:53: no such host,修改volume之后就好了。修改完后要重启runner,docker restart gitlab-runner1

项目配置

在Docker中把项目跑起来

我今天配置的是Vue项目,其他语言也差不多,换一下镜像和命令即可。首先是Dockerfile,一个很常规的docker配置文件,第一步使用nodejs构建,然后把打包后的文件复制到nginx容器中并运行nginx,为了方便,我把nginx.conf配置文件也贴出来吧。

# build stage
FROM docker.nju.edu.cn/node:lts as build-stage

WORKDIR /app
COPY . .
RUN yarn && yarn build

# production stage
FROM docker.nju.edu.cn/nginx:stable as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
server {
    listen 80;
    listen [::]:80;
    server_name _;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    location /assets/ {
        access_log off;
        add_header Cache-Control public;
        expires max;
        alias /usr/share/nginx/html/assets/;
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

有了上边两个文件,就可以在Docker中运行项目了,

.gitlab-ci.yml 文件

在项目根目录,创建一个.gitlab-ci.yml文件,内容如下

variables:
  IMAGE: ${CI_PROJECT_NAME}:${CI_PROJECT_NAMESPACE}-${CI_COMMIT_BRANCH}-${CI_COMMIT_SHORT_SHA}

stages:
  - build
  - deploy

build-image:
  stage: build
  image: docker.nju.edu.cn/docker:24
  script:
    - docker build -t ${IMAGE} .
  tags:
    - runner

deploy-to-server:
  stage: deploy
  when: on_success
  needs:
    - build-image

  script:
    - docker stop info-center-web1 && docker rm info-center-web1
    - docker run -d --name info-center-web1 -p 1895:80 ${IMAGE}

  tags:
    - runner

解释一下,首先是一些变量定义,用于镜像的tag。

构建分两个阶段,build和deploy,也有其他的可用,test之类的需要可以看文档。

build阶段就是简单的构建镜像用于运行,deploy阶段则是部署,我这里先把旧容器删掉,又启动了新容器,你可以根据实际情况修改,总之就是你手动运行Docker时怎么写,这里就怎么写。配置好提交到服务器应该就会触发自动部署了。可以在项目的CI/CD的pipelines里查看状态。如果你想自动构建,手动部署,就把yaml文件的when修改成manual,如果想只部署特定分支,也可以指明。gitlab提供了超多的功能选项,我这里知识抛砖引玉,有需要可以查看文档 https://docs.gitlab.com/ee/topics/build_your_application.html