gitlab CI教学

一、环境准备

  1. 腾讯云账号

  2. 上面购买三个CVM,两个4C8G,一个2C4G,系统都用Ubuntu 22.04

    • GITLAB_IP:GitLab 所在 CVM 的内网 IP,例如 192.168.1.2
    • HARBOR_IP:Harbor 所在 CVM 的内网 IP,例如 192.168.1.3
    • RUNNER_IP:Runner 所在 CVM 的内网 IP,例如 192.168.1.4
  3. 三个公网弹性公网ip,绑定给这3个机器。目的不是让他们通过公网互通,只是方便从官网拉镜像装包。在严格网络环境下,可以全部采用内网互通,不带公网,相关的镜像文件等东西,用一个能连上公网的机器下载下来,分别传给内网机器即可。这里从实验的角度来说,各配置一个弹性公网ip方便一点。

  4. 腾讯云镜像仓库地址:https://mirror.ccs.tencentyun.com

  5. 镜像文件:

    • docker:24 # 这个镜像要放到gitlab-runner的机器上
    • gitlab/gitlab-runner:alpine # 这个镜像要放到gitlab-runner的机器上
    • gitlab-ce-16.11.1.tar # 这个镜像要放到gitlab的机器上
    • gitlab/gitlab-runner-helper:x86_64-v18.9.0 # 这个镜像要docker pull到 gitlab-runner的机器上,因为跑CI job的时候要用,没有这个的话,跑pipeline job会报错,拉不到这个镜像,如图9.png
      在这里插入图片描述
  6. apt安装包:

    • docker.io
    • docker-compose
  7. 单独下载:

    • harbor-online-installer-v2.10.0.tgz # 是wget下载的压缩包,给harbor机器用
      (见第三节wget方式)
  8. 在三台机器上分别装docker 和 docker-compose(如果用的centos和rocky linux,高版本的rpm docker我记得一般是默认自带docker-compose的,但是Ubuntu得再装一下)

    apt install -y docker.io docker-compose

  9. 三台机器上都配置上腾讯云镜像仓库加速器

root@VM-1-2-ubuntu:/srv/gitlab# cat /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
}
root@VM-1-2-ubuntu:/srv/gitlab# 

修改 daemon.json 后,三台机器都要执行 systemctl restart docker,否则配置不生效

  1. 部署方式

在这里插入图片描述

二、部署gitlab服务

  1. 在gitlab的cvm上,创建gitlab工作目录

    mkdir -p /srv/gitlab && cd /srv/gitlab

  2. 写docker-compose.yml
root@VM-1-2-ubuntu:/srv/gitlab# cat docker-compose.yml 
version: "3.8"

services:
  gitlab:
    image: gitlab/gitlab-ce:16.11.1-ce.0
    container_name: gitlab
    restart: always
    hostname: 192.168.1.2
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'http://192.168.1.2' 
        # 要从公网访问gitlab UI,在上面创建runner时,会跳转为404,这时把这个ip改成gitlab机器的公网ip,等复制完创建runner时跳出的提示的,runner如何在gitlab注册的命令后,将ip再改回为内网ip,
        # 提示命令比如:docker exec -it gitlab-runner gitlab-runner register --url http://123.xxx.xx.xxx   --token glrt-xxvUZuNYexxx
    ports:
      - "80:80"
    volumes:
      - ./config:/etc/gitlab
      - ./logs:/var/log/gitlab
      - ./data:/var/opt/gitlab
root@VM-1-2-ubuntu:/srv/gitlab# 
  1. 用docker-compose启动gitlab服务,启动过程需要几分钟,大概3-5分钟。

    docker-compose up -d

  2. 过3分钟,检查gitlab是否部署成功
    • docker ps -a | grep gitlab

    • 用自己电脑浏览器访问gitlab机器的公网ip,应该要看到gitlab的登录界面
    • 默认登录用户root
    • 初始密码,在gitlab机器上执行如下命令
    • docker exec -it gitlab grep ‘Password:’ /etc/gitlab/initial_root_password

  3. 登录gitlab之后,修改root密码
  4. 在gitlab里面创建两个空项目
    • 代码仓库: demo-app,用来放java源码和.gitlab-ci.yml、Dockerfile、pom.xml
    • gitops仓库: demo-gitops,用来CD的时候弄argocd,放deployment.yaml

三、部署harbor

  1. 下载安装包

    wget https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-online-installer-v2.10.0.tgz

  2. 解压安装包

    tar xvf harbor-online-installer-v2.10.0.tgz

    cd harbor

  3. 复制示例配置

    cp harbor.yml.tmpl harbor.yml

  4. 修改配置:

    vim harbor.yml
    关键修改:

    • hostname: HARBOR_IP,这里用192.168.1.3
    • 使用 http:
      • port: 80
      • https: 块保持注释或 disabled,这里进行注释
    • 设定 admin 密码:harbor_admin_password: 你自定义
  5. 安装harbor

    ./install.sh

  6. 登录harbor

  • 默认用户: admin
  • 初始化密码: 在harbor.yml中自己自定义的
  1. 在harbor UI创建项目:demo
  2. 在harbor UI创建一个普通用户,要记录下这个用户的用户名和密码,作为HARBOR_USER和HARBOR_PASSWORD的值
  3. 在harbor UI点进项目demo里面,点击成员,添加刚才创建的普通用户,这个用户的角色定义为开发者

四、 部署gitlab-runner

  1. 在CVM机器上,对docker的配置,将harbor机器的内网ip设置成对于gitlab-runner机器来说是不安全的仓库
ubuntu@cvm-runner:~$ cat /etc/docker/daemon.json 
{
  "insecure-registries": ["192.168.1.3:80"],
  "registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
}
ubuntu@cvm-runner:~$
  1. 重启docker

    systemctl restart docker

  2. 拉取gitlab-runner的镜像

    docker pull gitlab/gitlab-runner:alpine

  3. 启动runner容器(挂载 docker.sock)

    mkdir -p /srv/gitlab-runner/config
    docker run -d --name gitlab-runner --restart always -v /srv/gitlab-runner/config:/etc/gitlab-runner -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:alpine

  4. 检查容器启动成功没

    docker ps

  5. 编辑 runner 配置(必须,否则 job 里 docker build 会失败) 「若当前还没有 [[runners]] 块,请先完成下面步骤 7、8 在 GitLab 创建 runner 并执行 register,再回到本步编辑 config.toml。」

    • 在 runner 宿主机上编辑:/srv/gitlab-runner/config/config.toml
    • [[runners]] 对应的 [runners.docker] 下确保有:
    privileged = true
    volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
    
    • 保存后无需重启容器,runner 会读配置;若已注册多个 runner,确认改的是当前用的那个 [[runners]] 块。

正确可用的效果如图:
在这里插入图片描述

  1. 在gitlab UI上创建runner,保存好token,UI点击路径如图,demo-app/CICD/settings/register runner

在这里插入图片描述

  1. 注册runner,在gitlab-runner所在机器上执行下方命令,具体如图

    docker exec -it gitlab-runner gitlab-runner register

    按照提示,先填gitlab的内网地址 http://192.168.1.2,和上一步记录下来的token

在这里插入图片描述

  1. 现在在终端里继续按顺序输入:

    • Runner 名字(随便写,比如):
      • cvm-runner-1
    • tag(可以直接回车留空):
      • Enter tags for the runner (comma-separated):
        [回车]
    • 是否运行 untagged jobs(建议选 true,直接回车默认值或输入 true):
      • Enter optional maintenance note for the runner:
        [回车]
      • Enter an executor: docker, shell, etc:
        docker
    • executor 选 docker,接着会让你输入 default image,比如:
      • Enter the default Docker image (for example, ruby:2.7):
        docker:24

    当命令结束、回到 shell 提示符时,注册就真正完成了。如图6.png

在这里插入图片描述

  1. 然后在 GitLab UI 里确认一下:

    • 进 demo-app → Settings → CI/CD → Runners
    • 在 Project runners 区块应看到一个 绿色 Active 的 runner(名字就是你刚填的 cvm-runner-1)

    如果是 Active,就说明 Runner 已经 OK,下一步你就可以开始写 .gitlab-ci.yml,在 UI 里点 Run pipeline 跑一次 CI 了。

在这里插入图片描述

  1. 在 demo-app → Settings → CI/CD → Variables 中配置 HARBOR_USERHARBOR_PASSWORD(建议勾选 Masked),否则下面 script 里的 docker login 会报错。

  2. 在gitlab UI创建新的runner的时候,会让填写tag,比如test04,这个tag如果定义了,那么在代码仓的.gitlab-ci.yml文件里面就要写build_and_push: [tags: [“test04”]],如图:

在这里插入图片描述

在这里插入图片描述

image: docker:24

variables:
  DOCKER_TLS_CERTDIR: ""

  HARBOR_HOST: "192.168.1.3:80"      # 换成你的 Harbor 内网 IP:80
  HARBOR_PROJECT: "demo"
  HARBOR_REPO: "spring-demo"
  IMAGE: "$HARBOR_HOST/$HARBOR_PROJECT/$HARBOR_REPO"

workflow:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "web"'
      when: always
    - when: never

stages:
  - docker

build_and_push:
  stage: docker
  tags: ["test04"]
  script:
    - docker info | grep -A3 "Insecure Registries" || true
    - docker login "$HARBOR_HOST" -u "$HARBOR_USER" -p "$HARBOR_PASSWORD"
    - docker build -t "$IMAGE:$CI_COMMIT_SHA" .
    - docker push "$IMAGE:$CI_COMMIT_SHA"
  only:
    - branches

五、准备java测试代码

代码仓里面放个简单的测试java源代码:

  1. 代码仓目录结构:
demo-app/
  pom.xml
  src/
    main/
      java/
        com/example/demo/
          DemoApplication.java
          HelloController.java
      resources/
        application.properties
  Dockerfile
  .gitlab-ci.yml
  1. pom.xml (Spring Boot 3 + Java 17)
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>demo</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>demo</name>
  <description>Demo Spring Boot app for CI/CD</description>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.3</version>
    <relativePath/>
  </parent>

  <properties>
    <java.version>17</java.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>
  1. 启动类 DemoApplication.java
    • 路径:src/main/java/com/example/demo/DemoApplication.java:
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
  1. 控制器 HelloController.java
    • 路径:src/main/java/com/example/demo/HelloController.java:
package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "hello from demo-app";
    }
}
  1. application.properties
    • 路径:src/main/resources/application.properties:
server.port=8080
management.endpoints.web.exposure.include=health,info
  1. Dockerfile
    • 放在项目根目录 demo-app/Dockerfile
FROM maven:3.9-eclipse-temurin-17 AS build
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn -B -Dmaven.test.skip=true clean package

FROM eclipse-temurin:17-jre
WORKDIR /app
COPY --from=build /app/target/*.jar /app/app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app/app.jar"]

六、 跑pipeline流水线

  1. 在gitlab的UI
  • demo-app → Build → Pipelines → Run pipeline
  • 构建应该可以顺利完成 Maven 打包 + Docker build/push,Harbor 里会出现一个新镜像。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

七、 补充说明

  1. gitlab-runner的机器里面的runner的容器里面,记得改过一个参数,但是忘了是哪一步改的了,如图就是这个提权,这个不改成true的话,job跑不通。

在这里插入图片描述

  1. 中间还有一步,是在gitlab UI上加环境变量HARBOR_USER和HARBOR_PASSWORD,将harbor上创建的用户,并且加入到了demo项目成员的用户的账号密码作为值,填到gitlab上,当gitlab-runner根据.gitlab-ci.yml里面的指引跑流水线的时候,可以找到这两个环境变量的值。如图14.png

在这里插入图片描述

八、总结

  1. 本次CI架构是基于gitlab和gitlab-runner来做的流水线,目的是通过这两个软件将java源代码,以.gitlab-ci.yml、Dockerfile、pom.xml为引导,通过gitlab-runner进程,来调用gitlab-runner容器所在宿主机的docker进程来在容器里面跑pipeline流水线,根据Dockerfile,基于一个基础镜像来在容器里面进行Maven然后在容器里面把jar包打好放到固定的位置,然后用java -jar命令启动这个jar包,也就是java程序。这样就做出来了一个java的服务镜像。这一步docker build -t的指引是写在.gitlab-ci.yml文件里面的。然后build好这个服务镜像之后,同样是根据.gitlab-ci.yml文件里面的指引步骤,将image push到harbor。这样就完成了一次,从java代码到build image,再到把image push到harbor的自动化流水线。之后每次开发提交代码之后,在gitlab上点一下build -> pipelines -> run pipeline,就可以以最新的commit为image的tag,把java代码Maven成jar包,打好服务镜像,并且把服务镜像推送到harbor了。这样一个CI就搞定了。那么第二步就是在argocd上去进行cd了,操作就是修改argocd watch的那个gitlab代码仓,里面就放上一个deployment.yaml就可以了。然后每次改一下deployment.yaml里面的image的tag,改成最新的。然后提交这次修改。当argocd监控到这个git仓库的变化之后,会自动把这个修改同步到TKE集群上。就完成了CD。CD这一步也可以手动到argocd UI上面去点,也可以设置好webhook对git仓库进行实时监控。

九、 再补充说明

  • GitLab:负责编排 pipeline 和下发 job
  • Runner 宿主机 (192.168.1.4):负责跑所有容器(runner / job / maven build)
  • Harbor (192.168.1.3:80):负责收镜像

十、后记(我让AI检查这篇教程,AI提出的问题,后面照着教程从零部署时,可能会遇到,我贴在这里)

整体来说,这篇教材思路清晰、步骤基本正确,用它从 0 搭一套 CI 完全没问题。有几处地方,如果补充说明一下,会更严谨、也更方便你以后“照着做”不踩坑:

1. 镜像 / 包准备的小细节
  • gitlab-ce-16.11.1.tar 的使用步骤没写
    你前面列了这个离线镜像,但后面 docker-compose.yml 直接用 gitlab/gitlab-ce:16.11.1-ce.0,没有写如果是离线环境要 docker load -i gitlab-ce-16.11.1.tar。建议在“环境准备”或“部署 gitlab”里加一句:
    docker load -i gitlab-ce-16.11.1.tar
    
  • 修改 /etc/docker/daemon.json 后记得重启 docker
    在 GitLab/Harbor 机器配置腾讯云镜像加速器时,最好像 runner 那里一样明确加一句:
    systemctl restart docker
    
2. GitLab Runner + Docker 的关键配置没写全

你现在的做法是:

  • runner 容器启动时挂了 -v /var/run/docker.sock:/var/run/docker.sock
  • 选的 executor 是 docker
  • .gitlab-ci.ymlimage: docker:24,直接在 job 里跑 docker build / docker push

要让这种模式稳定工作,config.toml 里有两个关键点建议写死在文档里(你现在只用截图提了一句“提权要改成 true”):

[[runners]]
  [runners.docker]
    privileged = true
    volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
  • privileged = true:就是你截图 13.png 里的那个,不改的话很多 docker build 会各种权限问题。
  • volumes 挂载 docker.sock:挂到 runner 容器上只是第一步,还需要在 config.toml 里把这个 volume 传递到真正跑 job 的容器里,否则 job 内看不到 /var/run/docker.sock

建议在“部署 gitlab-runner”里单独加一步“编辑 /srv/gitlab-runner/config/config.toml”,把这两个字段写清楚。

3. .gitlab-ci.yml 逻辑本身是通的,但可以再解释清楚一点
  • 当前写法是“job 容器里通过 docker.sock 操作宿主机 Docker”
    这一点你在总结里有提到,但建议在 .gitlab-ci.yml 段落前面明确一句:“这里不是起 docker:dind,而是通过 /var/run/docker.sock 调用 runner 宿主机的 Docker”——方便以后自己看时立刻想起来这是哪种模式。
  • HARBOR_USER / HARBOR_PASSWORD 的位置
    你在“补充说明”第 2 条里说了要在 GitLab UI 中配置这两个变量。可以在 .gitlab-ci.yml 段落前加一个“前置条件:在项目 Settings → CI/CD → Variables 中配置 HARBOR_USERHARBOR_PASSWORD”,这样一眼就看得到,不用看到后面补充说明才发现。
4. 版本和安全相关的提示(不是错误,但可提醒一下)
  • runner 版本与 helper 镜像
    你写了要提前拉 gitlab/gitlab-runner-helper:x86_64-v18.9.0,但没说明 runner 版本要与 helper 对齐(通常拉 gitlab/gitlab-runner:alpine-v18.9.0)。建议在拉 runner 镜像时带上版本号,并注明“helper 版本要与 runner 版本一致”。
  • HTTP Harbor + insecure-registries 的风险
    在“总结”或“补充说明”里加一句“生产环境建议给 Harbor 配 https,去掉 insecure-registries,这里只是为了教学方便”。
5. 文档结构上的小优化建议
  • 开头加一个总览图 / 步骤列表
    比如“1. 搭 GitLab → 2. 搭 Harbor → 3. 搭 Runner → 4. 准备 demo app → 5. 写 .gitlab-ci.yml → 6. 跑一次 Pipeline”,让你以后回来看时可以先整体扫一眼。
  • 把“容易忘的坑”集中成一小节 Checklist
    例如:
    • docker 的 /etc/docker/daemon.json 改完有没有重启
    • runner 的 privileged = true 是否改了
    • HARBOR_USERHARBOR_PASSWORD 是否配置在 GitLab Variables 里
    • helper 镜像是否提前拉好
    • pipeline 报错时先看 job log 里的哪一步挂了(登录 Harbor、build 还是 push)

总结一下:大方向和关键步骤是对的,可以成功跑通 CI,现在主要是少了 2~3 个关键配置的显式文字说明(尤其是 runner 的 config.toml 和 docker.sock),再加一点“坑点 checklist”,这篇教材就非常适合作为你以后反复复用的私有手册了。

如果你愿意,我可以帮你直接把这些修改合并进当前 gitlabCI教学.md,改成一个更完善的版本。

十一、 架构图

在这里插入图片描述

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐