- 在 CI/CD 作业中启用 Docker 命令
- 使用 Docker-in-Docker 中的镜像库进行身份验证
- 使用 Docker 层缓存使 Docker-in-Docker 构建速度更快
- 使用 OverlayFS 驱动程序
- Docker 替代方案
- 使用 GitLab Container Registry
-
故障排查
docker: Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?
- Docker
no such host
错误 - 错误:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock
- 错误:
unauthorized: incorrect username or password
- 连接期间的错误:
no such host
- 错误:
cgroups: cgroup mountpoint does not exist: unknown
使用 Docker 构建 Docker 镜像
您可以将 GitLab CI/CD 与 Docker 结合使用来创建 Docker 镜像。例如,您可以创建应用程序的 Docker 镜像,对其进行测试,然后将其发布到容器镜像库。
要在 CI/CD 作业中运行 Docker 命令,您必须配置 GitLab Runner 以支持 docker
命令。此方法需要 privileged
模式。
在 runner 上,如果你不想通过启用 privileged
模式来构建 Docker 镜像,你可以使用 Docker 替代方案。
在 CI/CD 作业中启用 Docker 命令
要为 CI/CD 作业启用 Docker 命令,您可以使用:
使用 shell executor
要在 CI/CD 作业中包含 Docker 命令,您可以将 runner 配置为使用 shell
executor。在此配置中,gitlab-runner
用户运行 Docker 命令,但需要权限才能这样做。
- 安装 GitLab Runner。
-
注册 一个 runner。 选择
shell
executor。例如:sudo gitlab-runner register -n \ --url https://gitlab.com/ \ --registration-token REGISTRATION_TOKEN \ --executor shell \ --description "My Runner"
-
在安装了极狐GitLab Runner 的服务器上,安装 Docker Engine。查看支持的平台列表。
-
将
gitlab-runner
用户添加到docker
组:sudo usermod -aG docker gitlab-runner
-
验证
gitlab-runner
是否可以访问 Docker:sudo -u gitlab-runner -H docker info
-
在极狐GitLab 中,为了验证一切正常,将
docker info
添加到.gitlab-ci.yml
:before_script: - docker info build_image: script: - docker build -t my-docker-image . - docker run my-docker-image /script/to/run/tests
您现在可以使用 docker
命令(并在需要时安装 docker-compose
)。
当您将 gitlab-runner
添加到 docker
组时,您实际上是在授予 gitlab-runner
完整的 root 权限。
了解更多关于 docker
组的安全性。
使用 Docker-in-Docker
“Docker-in-Docker”(dind
)意味着:
- 您注册的 runner 使用 Docker executor 或 Kubernetes executor。
- Executor 使用 Docker 提供的 Docker 容器镜像 来运行您的 CI/CD 作业。
Docker 镜像安装了所有的 docker
工具,并且可以在特权模式下,在镜像的上下文中运行作业脚本。
我们建议您使用 Docker-in-Docker with TLS enabled。
您应该始终指定镜像的特定版本,例如 docker:20.10.16
。
如果使用像 docker:stable
这样的标签,你就无法控制使用哪个版本。
可能会导致不可预测的行为,尤其是在发布新版本时。
将 Docker executor 与 Docker-in-Docker 一起使用
您可以使用 Docker executor 在 Docker 容器中运行作业。
在 Docker executor 中启用 TLS 的 Docker-in-Docker
Docker 守护进程支持通过 TLS 的连接。在 Docker 20.10.16 及更高版本中,TLS 是默认设置。
--docker-privileged
。当您这样做时,您实际上是在禁用容器的所有安全机制并将您的主机暴露给特权升级。这样做会导致 container breakout。有关更多信息,请参阅有关运行时权限和 Linux 功能 的官方 Docker 文档。要在启用 TLS 的情况下使用 Docker-in-Docker:
- 安装极狐GitLab Runner。
-
从命令行注册 GitLab Runner。使用
docker
和privileged
模式:sudo gitlab-runner register -n \ --url https://gitlab.com/ \ --registration-token REGISTRATION_TOKEN \ --executor docker \ --description "My Docker Runner" \ --docker-image "docker:20.10.16" \ --docker-privileged \ --docker-volumes "/certs/client"
- 这个命令注册一个新的 runner 来使用
docker:20.10.16
镜像。要启动构建和服务容器,它使用privileged
模式。如果您想使用 Docker-in-Docker,您必须始终在 Docker 容器中使用privileged = true
。 - 此命令为服务和构建容器挂载
/certs/client
,这是 Docker 客户端使用该目录中的证书所必需的。有关使用 TLS 的 Docker 如何工作的更多信息,请参阅 https://hub.docker.com/_/docker/#tls。
前面的命令创建了一个类似于这样的
config.toml
条目:[[runners]] url = "https://gitlab.com/" token = TOKEN executor = "docker" [runners.docker] tls_verify = false image = "docker:20.10.16" privileged = true disable_cache = false volumes = ["/certs/client", "/cache"] [runners.cache] [runners.cache.s3] [runners.cache.gcs]
- 这个命令注册一个新的 runner 来使用
-
您现在可以在作业脚本中使用
docker
。注意包含了docker:20.10.16-dind
服务:image: docker:20.10.16 variables: # When you use the dind service, you must instruct Docker to talk with # the daemon started inside of the service. The daemon is available # with a network connection instead of the default # /var/run/docker.sock socket. Docker 19.03 does this automatically # by setting the DOCKER_HOST in # https://github.com/docker-library/docker/blob/d45051476babc297257df490d22cbd806f1b11e4/19.03/docker-entrypoint.sh#L23-L29 # # The 'docker' hostname is the alias of the service container as described at # https://docs.gitlab.com/ee/ci/services/#accessing-the-services. # # Specify to Docker where to create the certificates. Docker # creates them automatically on boot, and creates # `/certs/client` to share between the service and job # container, thanks to volume mount from config.toml DOCKER_TLS_CERTDIR: "/certs" services: - docker:20.10.16-dind before_script: - docker info build: stage: build script: - docker build -t my-docker-image . - docker run my-docker-image /script/to/run/tests
在 Docker-in-Docker 和构建容器之间使用共享卷上的 Unix 套接字
在使用 Docker 执行器且启用了 TLS 的 Docker-in-Docker 模式中,在 volumes = ["/certs/client", "/cache"]
里定义的目录在各次构建之间是持久存在的。如果多个使用 Docker 执行器运行器的 CI/CD 作业都启用了 Docker-in-Docker 服务,那么每个作业都会向该目录路径写入数据。这种做法可能会导致冲突。
要解决此冲突,请在构建容器和 Docker-in-Docker 服务之间使用共享卷上的 Unix 套接字。此方法可提高性能,并在服务和客户端之间建立安全连接。
下面是一个示例 config.toml
,其中包含在构建容器和服务容器之间共享的临时卷:
[[runners]]
url = "https://gitlab.com/"
token = TOKEN
executor = "docker"
[runners.docker]
image = "docker:24.0.5"
privileged = true
volumes = ["/runner/services/docker"] # Temporary volume shared between build and service containers.
Docker-in-Docker 服务创建一个 docker.sock
。Docker 客户端通过 Docker Unix 套接字卷连接到 docker.sock
。
job:
variables:
# This variable is shared by both the DinD service and Docker client.
# For the service, it will instruct DinD to create `docker.sock` here.
# For the client, it tells the Docker client which Docker Unix socket to connect to.
DOCKER_HOST: "unix:///runner/services/docker/docker.sock"
services:
- docker:24.0.5-dind
image: docker:24.0.5
script:
- docker version
在 Docker executor 中禁用 TLS 的 Docker-in-Docker
有时您可能有正当理由禁用 TLS。 例如,您无法控制正在使用的 GitLab Runner 配置。
假设 runner 的 config.toml
类似于:
[[runners]]
url = "https://gitlab.com/"
token = TOKEN
executor = "docker"
[runners.docker]
tls_verify = false
image = "docker:20.10.16"
privileged = true
disable_cache = false
volumes = ["/cache"]
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
您现在可以在作业脚本中使用 docker
。请注意包含 docker:20.10.16-dind
服务:
image: docker:20.10.16
variables:
# When using dind service, you must instruct docker to talk with the
# daemon started inside of the service. The daemon is available with
# a network connection instead of the default /var/run/docker.sock socket.
#
# The 'docker' hostname is the alias of the service container as described at
# https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services
#
# If you're using GitLab Runner 12.7 or earlier with the Kubernetes executor and Kubernetes 1.6 or earlier,
# the variable must be set to tcp://localhost:2375 because of how the
# Kubernetes executor connects services to the job container
# DOCKER_HOST: tcp://localhost:2375
#
DOCKER_HOST: tcp://docker:2375
#
# This instructs Docker not to start over TLS.
DOCKER_TLS_CERTDIR: ""
services:
- docker:20.10.16-dind
before_script:
- docker info
build:
stage: build
script:
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests
将 Kubernetes executor 与 Docker-in-Docker 一起使用
您可以使用 Kubernetes executor 在 Docker 容器中运行作业。
在 Kubernetes 中启用了 TLS 的 Docker-in-Docker
要在 Kubernetes 中启用 TLS 的情况下使用 Docker-in-Docker:
-
使用 Helm chart,更新
values.yml
文件指定卷安装。runners: config: | [[runners]] [runners.kubernetes] image = "ubuntu:20.04" privileged = true [[runners.kubernetes.volumes.empty_dir]] name = "docker-certs" mount_path = "/certs/client" medium = "Memory"
-
您现在可以在作业脚本中使用
docker
。注意包含了docker:19.03.13-dind
服务:image: docker:19.03.13 variables: # When using dind service, you must instruct Docker to talk with # the daemon started inside of the service. The daemon is available # with a network connection instead of the default # /var/run/docker.sock socket. DOCKER_HOST: tcp://docker:2376 # # The 'docker' hostname is the alias of the service container as described at # https://docs.gitlab.com/ee/ci/services/#accessing-the-services. # If you're using GitLab Runner 12.7 or earlier with the Kubernetes executor and Kubernetes 1.6 or earlier, # the variable must be set to tcp://localhost:2376 because of how the # Kubernetes executor connects services to the job container # DOCKER_HOST: tcp://localhost:2376 # # Specify to Docker where to create the certificates. Docker # creates them automatically on boot, and creates # `/certs/client` to share between the service and job # container, thanks to volume mount from config.toml DOCKER_TLS_CERTDIR: "/certs" # These are usually specified by the entrypoint, however the # Kubernetes executor doesn't run entrypoints # https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4125 DOCKER_TLS_VERIFY: 1 DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client" services: - docker:19.03.13-dind before_script: - docker info build: stage: build script: - docker build -t my-docker-image . - docker run my-docker-image /script/to/run/tests
在 Kubernetes 中禁用了 TLS 的 Docker-in-Docker
要在 Kubernetes 使用禁用了 TLS 的 Docker-in-Docker,您必须将上面的示例调整为:
- 从
values.yml
文件中移除[[runners.kubernetes.volumes.empty_dir]]
部分。 - 将端口从
2376
改为2375
,使用DOCKER_HOST: tcp://docker:2375
。 - 指示 Docker 使用
DOCKER_TLS_CERTDIR: ""
启动时禁用 TLS。
例如:
-
使用 Helm chart更新
values.yml
文件:runners: config: | [[runners]] [runners.kubernetes] image = "ubuntu:20.04" privileged = true
-
现在你可以在作业脚本中使用
docker
了。你应该包含docker:24.0.5-dind
服务:default: image: docker:24.0.5 services: - docker:24.0.5-dind before_script: - docker info variables: # When using dind service, you must instruct Docker to talk with # the daemon started inside of the service. The daemon is available # with a network connection instead of the default # /var/run/docker.sock socket. DOCKER_HOST: tcp://docker:2375 # # The 'docker' hostname is the alias of the service container as described at # https://docs.gitlab.com/ee/ci/services/#accessing-the-services. # If you're using GitLab Runner 12.7 or earlier with the Kubernetes executor and Kubernetes 1.6 or earlier, # the variable must be set to tcp://localhost:2376 because of how the # Kubernetes executor connects services to the job container # DOCKER_HOST: tcp://localhost:2376 # # This instructs Docker not to start over TLS. DOCKER_TLS_CERTDIR: "" build: stage: build script: - docker build -t my-docker-image . - docker run my-docker-image /script/to/run/tests
Docker-in-Docker 的已知问题
Docker-in-Docker 是推荐的配置,但你需要注意以下问题:
-
docker-compose
命令:默认情况下,此命令在此配置中不可用。要在您的作业脚本中使用docker-compose
,请遵循docker-compose
安装说明。 - 缓存:每个作业都在新环境中运行。并发作业工作正常,因为每个构建都有自己的 Docker engine 实例,并且它们不会相互冲突。但是,作业可能会变慢,因为没有层缓存。
-
存储驱动程序:默认情况下,早期版本的 Docker 使用
vfs
存储驱动程序,它为每个作业复制文件系统。Docker 17.09 及更高版本使用--storage-driver overlay2
,这是推荐的存储驱动程序。有关详细信息,请参阅使用 OverlayFS 驱动程序。 -
根文件系统:因为
docker:20.10.16-dind
容器和 runner 容器不共享它们的根文件系统,您可以使用作业的工作目录作为子容器的挂载点。例如,如果您想与子容器共享文件,您可以在/builds/$CI_PROJECT_PATH
下创建一个子目录并将其用作挂载点。variables: MOUNT_POINT: /builds/$CI_PROJECT_PATH/mnt script: - mkdir -p "$MOUNT_POINT" - docker run -v "$MOUNT_POINT:/mnt" my-docker-image
将 Docker executor 与 Docker 套接字绑定一起使用
为了在你的 CI/CD 作业中使用 Docker 命令,你可以将 /var/run/docker.sock
挂载到容器中。然后就可以在镜像的上下文中使用 Docker 了。
如果你绑定了 Docker 套接字,那么你就不能将 docker:24.0.5-dind
作为服务了。卷绑定也会影响服务,它们是不兼容的。
要使 Docker 在镜像上下文中可用,您需要将 /var/run/docker.sock
挂载到启动的容器中。要使用 Docker executor 执行此操作,您需要将 "/var/run/docker.sock:/var/run/docker.sock"
添加到 [runners.docker]
部分的卷中。
您的配置应如下所示:
[[runners]]
url = "https://gitlab.com/"
token = RUNNER_TOKEN
executor = "docker"
[runners.docker]
tls_verify = false
image = "docker:20.10.16"
privileged = false
disable_cache = false
volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
[runners.cache]
Insecure = false
您也可以在注册 runner 时通过提供以下选项来执行此操作:
sudo gitlab-runner register -n \
--url "https://gitlab.com/" \
--registration-token REGISTRATION_TOKEN \
--executor docker \
--description "My Docker Runner" \
--docker-image "docker:24.0.5" \
--docker-volumes /var/run/docker.sock:/var/run/docker.sock
对于复杂的 Docker-in-Docker 设置,诸如使用 CodeClimate 进行代码质量扫描,您可能需要匹配主机和容器路径以确保正确执行。有关详细信息,请参阅使用私有 runner 进行 基于CodeClimate 的扫描。
为 docker:dind
服务启用镜像库镜像
当 Docker 守护进程在服务容器内启动时,它使用默认配置。您可能需要配置镜像库镜像 以提高性能,并确保您不会达到 Docker Hub 速率限制。
.gitlab-ci.yml
文件中的服务
您可以将额外的 CLI 标志附加到 dind
服务以设置镜像库镜像:
services:
- name: docker:19.03.13-dind
command: ["--registry-mirror", "https://registry-mirror.example.com"] # Specify the registry mirror to use
GitLab Runner 配置文件中的服务
如果您是 GitLab Runner 管理员,则可以指定 command
来为 Docker 守护程序配置镜像库镜像。必须为 Docker 或 Kubernetes executor 定义 dind
服务。
Docker:
[[runners]]
...
executor = "docker"
[runners.docker]
...
privileged = true
[[runners.docker.services]]
name = "docker:19.03.13-dind"
command = ["--registry-mirror", "https://registry-mirror.example.com"]
Kubernetes:
[[runners]]
...
name = "kubernetes"
[runners.kubernetes]
...
privileged = true
[[runners.kubernetes.services]]
name = "docker:19.03.13-dind"
command = ["--registry-mirror", "https://registry-mirror.example.com"]
极狐GitLab Runner 配置文件中的 Docker executor
如果您是 GitLab Runner 管理员,您可以为每个 dind
服务使用镜像。更新配置以指定卷挂载。
例如,如果您有一个包含以下内容的 /opt/docker/daemon.json
文件:
{
"registry-mirrors": [
"https://registry-mirror.example.com"
]
}
更新 config.toml
文件,将文件挂载到 /etc/docker/daemon.json
。这将为 GitLab Runner 创建的每个容器挂载文件。配置由 dind
服务获取。
[[runners]]
...
executor = "docker"
[runners.docker]
image = "alpine:3.12"
privileged = true
volumes = ["/opt/docker/daemon.json:/etc/docker/daemon.json:ro"]
极狐GitLab Runner 配置文件中的 Kubernetes executor
如果您是极狐GitLab Runner 管理员,您可以为每个 dind
服务使用镜像。更新配置以指定 ConfigMap 卷挂载。
例如,如果您有一个包含以下内容的 /tmp/daemon.json
文件:
{
"registry-mirrors": [
"https://registry-mirror.example.com"
]
}
使用该文件的内容创建一个 ConfigMap。您可以使用以下命令执行此操作:
kubectl create configmap docker-daemon --namespace gitlab-runner --from-file /tmp/daemon.json
创建 ConfigMap 后,您可以更新 config.toml
文件,将文件挂载到 /etc/docker/daemon.json
。此更新为 GitLab Runner 创建的每个容器挂载文件。
配置由 dind
服务获取。
[[runners]]
...
executor = "kubernetes"
[runners.kubernetes]
image = "alpine:3.12"
privileged = true
[[runners.kubernetes.volumes.config_map]]
name = "docker-daemon"
mount_path = "/etc/docker/daemon.json"
sub_path = "daemon.json"
Docker 套接字绑定的已知问题
使用 Docker 套接字绑定时,可以避免在特权模式下运行 Docker。但是,这种方法:
- 通过共享 Docker 守护进程,您可以有效地禁用容器的所有安全机制,并使您的主机暴露在权限提升中,这可能导致 container breakout。例如,如果一个项目运行
docker rm -f $(docker ps -a -q)
,它将删除 GitLab Runner 容器。 - 并发作业可能不起作用;如果您的测试创建具有特定名称的容器,它们可能会相互冲突。
- 任何由 Docker 命令生成的容器都是 runner 的 siblings,而不是 runner 的子节点。这可能具有不适合您的工作流程的复杂性和限制。
-
将源仓库中的文件和目录共享到容器中可能无法按预期工作。卷挂载是在 host machine context 中完成的,而不是构建容器。例如:
docker run --rm -t -i -v $(pwd)/src:/home/app/src test-image:latest run_app_tests
您不需要像使用 Docker-in-Docker executor 时那样包含 docker:20.10.16-dind
服务:
image: docker:20.10.16
before_script:
- docker info
build:
stage: build
script:
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests
使用 Docker-in-Docker 中的镜像库进行身份验证
当您使用 Docker-in-Docker 时,标准身份验证方法不起作用,因为新的 Docker 守护进程随服务一起启动。
使用 Docker 层缓存使 Docker-in-Docker 构建速度更快
使用 Docker-in-Docker 时,每次创建构建时,Docker 都会下载镜像的所有层。Docker 的最新版本(Docker 1.13 及更高版本)可以在 docker build
步骤中使用预先存在的镜像作为缓存。这大大加快了构建过程。
使用 OverlayFS 驱动程序
默认情况下,当使用 docker:dind
时,Docker 使用 vfs
存储驱动程序,它会在每次运行时复制文件系统。这是一个磁盘密集型操作,如果使用不同的驱动程序可以避免,例如 overlay2
。
要求
- 确保使用最新的内核,最好是
>= 4.2
。 -
检查是否加载了
overlay
模块:sudo lsmod | grep overlay
如果看不到结果,则说明未加载。要加载它,请使用:
sudo modprobe overlay
如果一切顺利,您需要确保在重新启动时加载模块。在 Ubuntu 系统上,这是通过编辑
/etc/modules
来完成的。只需在其中添加以下行:overlay
每个项目使用 OverlayFS 驱动程序
您可以通过使用 .gitlab-ci.yml
中的 DOCKER_DRIVER
CI/CD 变量 为每个项目单独启用驱动程序:
variables:
DOCKER_DRIVER: overlay2
为每个项目使用 OverlayFS 驱动程序
如果您使用自己的 runners,则可以通过在 [[runners]]
部分中设置 DOCKER_DRIVER
环境变量来为每个项目启用驱动程序 config.toml
文件:
environment = ["DOCKER_DRIVER=overlay2"]
如果您正在运行多个 runner,则必须修改所有配置文件。
Docker 替代方案
To build Docker images without enabling privileged mode on the runner, you can use one of these alternatives: 要想在 runner 上不启用特权模式就能构建 Docker 镜像,您可以使用以下替代方案之一:
Buildah 示例
要在极狐GitLab CI/CD 中使用 Buildah,您需要使用以下执行器之一的 runner:
在此示例中,你可以用 Buildah 来:
- 构建一个 Docker 镜像。
- 将其推送到极狐GitLab 容器镜像仓库。
在最后的步骤中,Buildah 使用项目根目录下的 Dockerfile
来构建 Docker 镜像。最后,它将镜像推送到项目的容器镜像仓库中。
build:
stage: build
image: quay.io/buildah/stable
variables:
# Use vfs with buildah. Docker offers overlayfs as a default, but Buildah
# cannot stack overlayfs on top of another overlayfs filesystem.
STORAGE_DRIVER: vfs
# Write all image metadata in the docker format, not the standard OCI format.
# Newer versions of docker can handle the OCI format, but older versions, like
# the one shipped with Fedora 30, cannot handle the format.
BUILDAH_FORMAT: docker
FQ_IMAGE_NAME: "$CI_REGISTRY_IMAGE/test"
before_script:
# GitLab container registry credentials taken from the
# [predefined CI/CD variables](../variables/index.md#predefined-cicd-variables)
# to authenticate to the registry.
- echo "$CI_REGISTRY_PASSWORD" | buildah login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
script:
- buildah images
- buildah build -t $FQ_IMAGE_NAME
- buildah images
- buildah push $FQ_IMAGE_NAME
如果你正在使用 GitLab Runner Operator 部署到 OpenShift 集群,请尝试使用 Buildah 在无根容器中构建镜像的教程。
使用 GitLab Container Registry
构建 Docker 镜像后,您可以将其推送到内置的 GitLab Container Registry。
故障排查
docker: Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?
当您使用 Docker-in-Docker v19.03 或更高版本时,这是一个常见错误。
出现此问题是因为 Docker 自动在 TLS 上启动。
Docker no such host
错误
您可能会收到一条错误消息:docker: error during connect: Post https://docker:2376/v1.40/containers/create: dial tcp: lookup docker on x.x.x.x:53: no such host
。
当服务的镜像名称包括镜像库主机名时,可能会发生此问题。例如:
image: docker:20.10.16
services:
- registry.hub.docker.com/library/docker:20.10.16-dind
服务的主机名是派生自完整镜像名称。然而,预期是较短的服务主机名 docker
。要允许服务解析和访问,请为服务名称 docker
添加显式别名:
image: docker:20.10.16
services:
- name: registry.hub.docker.com/library/docker:20.10.16-dind
alias: docker
错误: Cannot connect to the Docker daemon at unix:///var/run/docker.sock
当尝试运行 docker
命令来访问 dind
服务时,您可能会收到以下错误:
$ docker ps
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
确保你的作业已经定义了这些环境变量:
DOCKER_HOST
-
DOCKER_TLS_CERTDIR
(可选) -
DOCKER_TLS_VERIFY
(可选)
你可能还想要更新提供 Docker 客户端的镜像。例如,docker/compose
镜像已过时并且应该被 docker
替换。
如果你的作业之前依赖于从已弃用的 Docker --link
参数 派生的环境变量,例如 DOCKER_PORT_2375_TCP
,就会出现此错误。如果发生以下情况,你的作业就会因为此错误而失败:
- 你的 CI/CD 镜像依赖一个传统的变量,诸如
DOCKER_PORT_2375_TCP
。 -
runner 功能标志
FF_NETWORK_PER_BUILD
被设置为true
。
错误: unauthorized: incorrect username or password
当使用弃用的变量 CI_BUILD_TOKEN
,就会出现如下错误:
Error response from daemon: Get "https://registry-1.docker.io/v2/": unauthorized: incorrect username or password
要阻止用户接收到此错误,你应该:
- 使用 CI_JOB_TOKEN取而代之。
- 从
gitlab-ci-token/CI_BUILD_TOKEN
改为$CI_REGISTRY_USER/$CI_REGISTRY_PASSWORD
。
连接期间的错误: no such host
当 dind
服务启动失败就会出现如下错误:
error during connect: Post "https://docker:2376/v1.24/auth": dial tcp: lookup docker on 127.0.0.11:53: no such host
检查作业日志以查看是否出现 mount: permission denied (are you root?)
。例如:
Service container logs:
2023-08-01T16:04:09.541703572Z Certificate request self-signature ok
2023-08-01T16:04:09.541770852Z subject=CN = docker:dind server
2023-08-01T16:04:09.556183222Z /certs/server/cert.pem: OK
2023-08-01T16:04:10.641128729Z Certificate request self-signature ok
2023-08-01T16:04:10.641173149Z subject=CN = docker:dind client
2023-08-01T16:04:10.656089908Z /certs/client/cert.pem: OK
2023-08-01T16:04:10.659571093Z ip: can't find device 'ip_tables'
2023-08-01T16:04:10.660872131Z modprobe: can't change directory to '/lib/modules': No such file or directory
2023-08-01T16:04:10.664620455Z mount: permission denied (are you root?)
2023-08-01T16:04:10.664692175Z Could not mount /sys/kernel/security.
2023-08-01T16:04:10.664703615Z AppArmor detection and --privileged mode might break.
2023-08-01T16:04:10.665952353Z mount: permission denied (are you root?)
这意味着极狐GitLab Runner 没有权限来启动 dind
服务:
- 检查在
config.toml
中privileged = true
的设置是否正确。 - 确保 CI 作业具有正确的 Runner 标签以使用这些特权 Runner。
错误: cgroups: cgroup mountpoint does not exist: unknown
这是 Docker Engine 20.10 引入的已知不兼容性。
当宿主机使用 Docker Engine 20.10 或更高版本时,版本低于 20.10 的 docker:dind
服务将无法正常工作。
尽管服务自身启动不会有问题,但是尝试构建容器镜像就会出现如下问题:
cgroups: cgroup mountpoint does not exist: unknown
要解决此问题,请将 docker:dind
容器更新到至少 20.10.x 版本,例如 docker:24.0.5-dind
。
相反的配置(docker:24.0.5-dind
服务和宿主机上 Docker Engine 的版本为 19.06.x 或更低版本)不会出现问题。对于最佳策略,您应该经常测试和更新作业环境版本到最新版本。这带来了新的功能、改进的安全性和 - 对于这个特定案例 - 使升级底层 Docker Engine 在 runner 的主机上对作业透明。