> 技术文档 > 创建 GitLab Runner 使用CICD自动化部署容器

创建 GitLab Runner 使用CICD自动化部署容器

包括创建 GitLab Runner 的 Docker 命令和注册 Runner 的步骤,以及 .gitlab-ci.yml 文件的内容。
直接在宿主机上使用 Docker

  • 定义: 在宿主机上安装并使用 Docker 服务意味着 Docker daemon 直接在宿主机操作系统上运行。
  • 用途: 适用于任何需要构建、运行或管理 Docker 容器的场景。这是最常见的 Docker 使用方式。
  • 特权模式: 不需要特别的权限设置,因为 Docker daemon 已经作为系统服务运行。
  • 网络集成: 宿主机上的 Docker daemon 能够直接利用宿主机的网络栈,因此网络配置更加直接且高效。
  • 资源管理: 由于 Docker daemon 是直接运行在宿主机上的,因此没有额外的资源开销用于运行 Docker daemon 自身。

创建 GitLab Runner

创建config.toml

[root@k8s local]# docker exec -it gitlab-runner cat /etc/gitlab-runner/config.tomlconcurrent = 1check_interval = 0connection_max_age = \"15m0s\"shutdown_timeout = 0[session_server] session_timeout = 1800[[runners]] name = \"docker\" url = \"http://192.168.0.3\" id = 1 token = \"glrt-jjiRpadeKbwuLRasNVPogW86MQpwOjEKdDozCnU6Mg8.01.170obpunv\" executor = \"docker\" [runners.cache] MaxUploadedArchiveSize = 0 [runners.docker] tls_verify = false image = \"maven:3.8.6-jdk-11\" privileged = true disable_entrypoint_overwrite = false oom_kill_disable = false disable_cache = false volumes = [\"/cache\", \"/var/run/docker.sock:/var/run/docker.sock\"] shm_size = 0 network_mtu = 0 allowed_pull_policies = [\"always\", \"if-not-present\"]

首先,使用以下命令创建 GitLab Runner:

docker run -d --name gitlab-runner \\ --restart always \\ --privileged \\ -v /srv/gitlab-runner/config:/etc/gitlab-runner \\ -v /var/run/docker.sock:/var/run/docker.sock \\ -v /usr/local/daemon.json:/etc/docker/daemon.json \\ -v /usr/local/config.toml:/etc/gitlab-runner/config.toml \\ gitlab/gitlab-runner:latest

此命令做了以下几件事:

-d:后台运行容器。
–name gitlab-runner:指定容器名称为 gitlab-runner。
–restart always:设置重启策略为总是重启。
–privileged:赋予容器扩展权限,以便它可以管理宿主机的 Docker 守护进程。
-v /srv/gitlab-runner/config:/etc/gitlab-runner:挂载配置目录。
-v /var/run/docker.sock:/var/run/docker.sock:允许容器与 Docker 守护进程通信。
-v /usr/local/daemon.json:/etc/docker/daemon.json 和 -v /usr/local/config.toml:/etc/gitlab-runner/config.toml:挂载自定义配置文件

注册 GitLab Runner

docker exec -it gitlab-runner gitlab-runner register

然后按照提示输入以下信息:

GitLab 实例的 URL (例如 http://192.168.0.3)
GitLab 提供的注册令牌(可以从 GitLab 管理员界面获取)
描述 Runner
标签(如 docker)
Executor 类型(在这个例子中选择 docker)

.gitlab-ci.yml 示例

image: name: maven:3.8.6-jdk-11 pull_policy: if-not-presentvariables: DOCKER_TLS_CERTDIR: \"\" IMAGE_NAME: \"jvue:latest\" DOCKER_CLIENT_TIMEOUT: 600 COMPOSE_HTTP_TIMEOUT: 600stages: - build - deploybefore_script: - echo \"deb http://mirrors.aliyun.com/debian/ bullseye main contrib non-free\" > /etc/apt/sources.list - echo \"deb http://mirrors.aliyun.com/debian/ bullseye-updates main contrib non-free\" >> /etc/apt/sources.list - echo \"deb http://mirrors.aliyun.com/debian-security bullseye-security main contrib non-free\" >> /etc/apt/sources.list - until apt-get update; do sleep 5; done - until apt-get install -y --fix-missing docker.io; do sleep 5; donebuild: stage: build tags: - docker script: - mvn clean package -DskipTests=true - docker build -t $IMAGE_NAME . timeout: 3hdeploy: stage: deploy tags: - docker script: - | docker stop my-springboot-app || true docker rm my-springboot-app || true docker run -d \\ --name my-springboot-app \\ --network bridge \\ -p 8080:8080 \\ -e SPRING_DATASOURCE_URL=\'jdbc:mysql://192.168.0.3:13306/jvue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\' \\ -e SPRING_DATASOURCE_USERNAME=root \\ -e SPRING_DATASOURCE_PASSWORD=12345678 \\ -e SPRING_REDIS_HOST=192.168.0.3 \\ -e SPRING_REDIS_PORT=16379 \\ -e SPRING_REDIS_DATABASE=0 \\ -e SPRING_REDIS_PASSWORD=12345678 \\ $IMAGE_NAME timeout: 3h

确保所有路径、变量、URL 和凭据都已正确设置,并且符合你项目的实际需求。这样,你就完成了从创建 Runner 到配置 .gitlab-ci.yml 文件的一整套流程。

Dockerfile 用于构建 Spring Boot 应用的镜像

FROM openjdk:11-jdk-slim
WORKDIR /app
COPY jvue-admin/target/*.jar app.jar
ENTRYPOINT [“java”, “-jar”, “app.jar”]

执行CICD流水线

确保所有路径、变量、URL 和凭据都已正确设置,并且符合你项目的实际需求。这样,你就完成了从创建 Runner 到配置 .gitlab-ci.yml 文件的一整套流程。

使用docker:20.10-dind

以在一个 Docker 容器内启动另一个 Docker 容器

docker:20.10-dind (Docker in Docker)

  • 定义: docker:20.10-dind 是一个 Docker 镜像,它包含了完整的 Docker 服务(即 Docker
    daemon)。这意味着你可以在一个 Docker 容器内启动另一个 Docker 容器。
  • 用途: 主要用于 CI/CD 管道中,在容器化环境中提供 Docker 构建能力。例如,在 GitLab CI 中,你可能需要在一个
    Docker 容器中构建 Docker 镜像。
  • 特权模式: 运行 docker:dind 容器时通常需要使用 --privileged 标志来给予额外权限,因为 Docker
    daemon 需要管理宿主机上的资源。
  • 网络隔离: docker:dind 容器内的 Docker daemon
    可能会有自己的网络命名空间,这意味着容器内部的网络配置可能会与宿主机不同。
  • 资源消耗: 使用 docker:dind 意味着你需要为 Docker daemon 分配额外的资源,这会增加一些开销。

关键差异点

  • 复杂性: 使用 docker:dind 增加了系统的复杂性,因为你现在有两个 Docker daemon
    实例——一个是宿主机上的,另一个是容器内的。而在宿主机上直接使用 Docker 则不需要处理这种复杂性。
  • 性能: 直接在宿主机上运行 Docker 通常会有更好的性能,因为减少了中间层(如容器化的 Docker daemon)带来的性能损耗。
  • 隔离性: docker:dind
    提供了一定程度的隔离性,这对于某些安全敏感的应用场景是有益的。然而,这也可能导致网络和其他方面的复杂性增加。
  • 部署灵活性: 使用 docker:dind 可以让你更容易地在不同的环境之间迁移你的 CI/CD 流程,因为它不依赖于宿主机的具体
    Docker 版本或配置。

修改关键点

  1. 移除宿主机 Docker 套接字的挂载:当你使用 docker:dind 时,你不应该再挂载宿主机的
    /var/run/docker.sock。相反,你应该让容器内部运行一个独立的 Docker 守护进程。
  2. 配置服务启动参数:你已经尝试在 [runners.service_args] 中配置了 Docker
    守护进程的启动参数。这是正确的方向,但需要确保这些参数适用于 docker:dind 的启动方式。
  3. 调整 GitLab Runner 配置文件:确保你的 GitLab Runner 配置正确地反映了你希望使用 docker:dind
    的意图,并且没有遗留的与宿主机 Docker 相关的配置。
[root@k8s local]# cat config.tomlconcurrent = 1check_interval = 0connection_max_age = \"15m0s\"shutdown_timeout = 0[session_server] session_timeout = 1800[[runners]] name = \"docker\" url = \"http://192.168.0.3\" id = 1 token = \"glrt-jjiRpadeKbwuLRasNVPogW86MQpwOjEKdDozCnU6Mg8.01.170obpunv\" executor = \"docker\" [runners.cache] MaxUploadedArchiveSize = 0 [runners.docker] tls_verify = false image = \"docker:20.10-dind\" # 使用 docker:dind 作为基础镜像 privileged = true  # 必须为 true 来允许 dind 正常工作 disable_entrypoint_overwrite = false oom_kill_disable = false disable_cache = false volumes = [\"/cache\", \"/certs/client\"] # 注意这里不再挂载 /var/run/docker.sock shm_size = 0 network_mtu = 0 allowed_pull_policies = [\"always\", \"if-not-present\"] [runners.services] - name = \"docker:20.10-dind\" command = [\"--registry-mirror=https://docker.mirrors.ustc.edu.cn\", \"--registry-mirror=https://mirror.iscas.ac.cn\", \"--host=unix:///var/run/docker.sock\", \"--host=tcp://0.0.0.0:2375\", \"--storage-driver=vfs\", \"--dns=8.8.8.8\", \"--dns=8.8.4.4\", \"--max-concurrent-downloads=10\", \"--max-download-attempts=5\"]

修改.gitlab-ci.yml

image: name: maven:3.8.6-jdk-11 # 使用较新的 JDK 和 Maven 版本,通常基于较新的操作系统 pull_policy: if-not-presentservices: - name: docker:20.10-dind alias: docker variables: DOCKER_TLS_CERTDIR: \"\"variables: DOCKER_HOST: tcp://docker:2375 # 指定 Docker 守护进程地址 DOCKER_CLIENT_TIMEOUT: 600 COMPOSE_HTTP_TIMEOUT: 600 IMAGE_NAME: \"jvue:latest\"stages: - build - deploybefore_script: - echo \"deb http://mirrors.aliyun.com/debian/ bullseye main contrib non-free\" > /etc/apt/sources.list - echo \"deb http://mirrors.aliyun.com/debian/ bullseye-updates main contrib non-free\" >> /etc/apt/sources.list - echo \"deb http://mirrors.aliyun.com/debian-security bullseye-security main contrib non-free\" >> /etc/apt/sources.list - until apt-get update; do sleep 5; done # 移除了 docker.io 的安装步骤,因为我们将使用 DinDbuild: stage: build tags: - docker script: - mvn clean package -DskipTests=true - docker build -t $IMAGE_NAME . - docker push $IMAGE_NAME # 如果你需要推送镜像到某个仓库,请取消注释此行 timeout: 3hdeploy: stage: deploy tags: - docker script: - | docker stop my-springboot-app || true docker rm my-springboot-app || true docker run -d \\ --name my-springboot-app \\ --network bridge \\ -p 8080:8080 \\ -e SPRING_DATASOURCE_URL=\'jdbc:mysql://192.168.0.3:13306/jvue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\' \\ -e SPRING_DATASOURCE_USERNAME=root \\ -e SPRING_DATASOURCE_PASSWORD=12345678 \\ -e SPRING_REDIS_HOST=192.168.0.3 \\ -e SPRING_REDIS_PORT=16379 \\ -e SPRING_REDIS_DATABASE=0 \\ -e SPRING_REDIS_PASSWORD=12345678 \\ $IMAGE_NAME timeout: 3h