创建 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.toml
concurrent = 1
check_interval = 0
connection_max_age = "15m0s"
shutdown_timeout = 0[session_server]session_timeout = 1800[[runners]]name = "docker"url = "http://192.168.0.3"id = 1token = "glrt-jjiRpadeKbwuLRasNVPogW86MQpwOjEKdDozCnU6Mg8.01.170obpunv"executor = "docker"[runners.cache]MaxUploadedArchiveSize = 0[runners.docker]tls_verify = falseimage = "maven:3.8.6-jdk-11"privileged = truedisable_entrypoint_overwrite = falseoom_kill_disable = falsedisable_cache = falsevolumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]shm_size = 0network_mtu = 0allowed_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-11pull_policy: if-not-presentvariables:DOCKER_TLS_CERTDIR: ""IMAGE_NAME: "jvue:latest"DOCKER_CLIENT_TIMEOUT: 600COMPOSE_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: buildtags:- dockerscript:- mvn clean package -DskipTests=true- docker build -t $IMAGE_NAME .timeout: 3hdeploy:stage: deploytags:- dockerscript:- |docker stop my-springboot-app || truedocker rm my-springboot-app || truedocker 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_NAMEtimeout: 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 版本或配置。
修改关键点
- 移除宿主机 Docker 套接字的挂载:当你使用 docker:dind 时,你不应该再挂载宿主机的
/var/run/docker.sock。相反,你应该让容器内部运行一个独立的 Docker 守护进程。 - 配置服务启动参数:你已经尝试在 [runners.service_args] 中配置了 Docker
守护进程的启动参数。这是正确的方向,但需要确保这些参数适用于 docker:dind 的启动方式。 - 调整 GitLab Runner 配置文件:确保你的 GitLab Runner 配置正确地反映了你希望使用 docker:dind
的意图,并且没有遗留的与宿主机 Docker 相关的配置。
[root@k8s local]# cat config.toml
concurrent = 1
check_interval = 0
connection_max_age = "15m0s"
shutdown_timeout = 0[session_server]session_timeout = 1800[[runners]]name = "docker"url = "http://192.168.0.3"id = 1token = "glrt-jjiRpadeKbwuLRasNVPogW86MQpwOjEKdDozCnU6Mg8.01.170obpunv"executor = "docker"[runners.cache]MaxUploadedArchiveSize = 0[runners.docker]tls_verify = falseimage = "docker:20.10-dind" # 使用 docker:dind 作为基础镜像privileged = true # 必须为 true 来允许 dind 正常工作disable_entrypoint_overwrite = falseoom_kill_disable = falsedisable_cache = falsevolumes = ["/cache", "/certs/client"] # 注意这里不再挂载 /var/run/docker.sockshm_size = 0network_mtu = 0allowed_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-dindalias: dockervariables:DOCKER_TLS_CERTDIR: ""variables:DOCKER_HOST: tcp://docker:2375 # 指定 Docker 守护进程地址DOCKER_CLIENT_TIMEOUT: 600COMPOSE_HTTP_TIMEOUT: 600IMAGE_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: buildtags:- dockerscript:- mvn clean package -DskipTests=true- docker build -t $IMAGE_NAME .- docker push $IMAGE_NAME # 如果你需要推送镜像到某个仓库,请取消注释此行timeout: 3hdeploy:stage: deploytags:- dockerscript:- |docker stop my-springboot-app || truedocker rm my-springboot-app || truedocker 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_NAMEtimeout: 3h