包括创建 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
bash
[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 = 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:
bash
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
bash
docker exec -it gitlab-runner gitlab-runner register
然后按照提示输入以下信息:
GitLab 实例的 URL (例如 http://192.168.0.3)
GitLab 提供的注册令牌(可以从 GitLab 管理员界面获取)
描述 Runner
标签(如 docker)
Executor 类型(在这个例子中选择 docker)
.gitlab-ci.yml 示例
yaml
image:
name: maven:3.8.6-jdk-11
pull_policy: if-not-present
variables:
DOCKER_TLS_CERTDIR: ""
IMAGE_NAME: "jvue:latest"
DOCKER_CLIENT_TIMEOUT: 600
COMPOSE_HTTP_TIMEOUT: 600
stages:
- build
- deploy
before_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; done
build:
stage: build
tags:
- docker
script:
- mvn clean package -DskipTests=true
- docker build -t $IMAGE_NAME .
timeout: 3h
deploy:
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 版本或配置。
修改关键点
- 移除宿主机 Docker 套接字的挂载:当你使用 docker:dind 时,你不应该再挂载宿主机的
/var/run/docker.sock。相反,你应该让容器内部运行一个独立的 Docker 守护进程。 - 配置服务启动参数:你已经尝试在 [runners.service_args] 中配置了 Docker
守护进程的启动参数。这是正确的方向,但需要确保这些参数适用于 docker:dind 的启动方式。 - 调整 GitLab Runner 配置文件:确保你的 GitLab Runner 配置正确地反映了你希望使用 docker:dind
的意图,并且没有遗留的与宿主机 Docker 相关的配置。
bash
[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 = 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
yaml
image:
name: maven:3.8.6-jdk-11 # 使用较新的 JDK 和 Maven 版本,通常基于较新的操作系统
pull_policy: if-not-present
services:
- 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
- deploy
before_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 的安装步骤,因为我们将使用 DinD
build:
stage: build
tags:
- docker
script:
- mvn clean package -DskipTests=true
- docker build -t $IMAGE_NAME .
- docker push $IMAGE_NAME # 如果你需要推送镜像到某个仓库,请取消注释此行
timeout: 3h
deploy:
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