从 GitLab CI 运行器连接到 docker-in-docker

Posted

技术标签:

【中文标题】从 GitLab CI 运行器连接到 docker-in-docker【英文标题】:Connecting to docker-in-docker from a GitLab CI runner 【发布时间】:2018-01-01 03:15:08 【问题描述】:

我有一个我想要的 GitLab 管道:

    构建 Java 应用程序 使用 docker-compose 进行测试 推送到我的 Docker 存储库

我遇到的主要问题是这有效

services:
  - docker:dind

docker_test:
  stage: docker_test
  image: docker:latest
  script:
  - docker version

按预期打印输出:

> gitlab-ci-multi-runner exec docker --docker-privileged docker_test
...
$ docker version
Client:
 Version:      17.06.0-ce
...
Server:
 Version:      17.06.0-ce
...
Build succeeded

虽然没有docker-ce 的安装步骤省略):

services:
  - docker:dind

docker_test:
  stage: docker_test
  image: ubuntu:latest       << note change
  script:
  - docker version

它失败了:

$ docker version
Client:
 Version:      17.06.0-ce
 API version:  1.30
 Go version:   go1.8.3
 Git commit:   02c1d87
 Built:        Fri Jun 23 21:23:31 2017
 OS/Arch:      linux/amd64
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
ERROR: Build failed: exit code 1
FATAL: exit code 1

如何使我的ubuntu 映像(或将构建我的项目的任何映像)连接到链接的 Docker-in-Docker 服务? docker:latest 做了什么我没有做的事?

我已经阅读了GitLab services documentation,但这仅从主机名的角度对我有意义。 (如果你有mysql 服务,你可以通过mysql:3306 连接。)

编辑:将命令更新为echo $DOCKER_HOST,我在docker:latest 图像中看到:

$ echo $DOCKER_HOST
tcp://docker:2375

ubuntu:latest 图像中我看到:

$ echo $DOCKER_HOST
(nothing - but SO doesn't let me add a blank code line)

【问题讨论】:

你能在这两个例子中都这样做吗?而不是docker version,这样做echo $DOCKER_HOST 感谢@Robert - 答案已更新。看起来 $DOCKER_HOST 未在 Ubuntu 映像中设置。 tcp://docker:2375 是一个足够恒定的值,我应该将变量导出到我的 Dockerfile 中,还是有更好的/编程方式来确定它? 我已将建议作为答案发布。请告诉我它是否有效。 我认为这将是一个固定值,所以硬编码没有问题。也不算丑。 谢谢@Robert - 但看起来这绝对是诀窍。我仍在整理并仔细检查,但会通知您。 【参考方案1】:

作为您添加的信息,我希望这确实有效:

services:
  - docker:dind

docker_test:
  stage: docker_test
  image: ubuntu:latest
  variables:
      DOCKER_HOST: "tcp://docker:2375"
  script:
  - docker version

或者:

services:
  - docker:dind

docker_test:
  stage: docker_test
  image: ubuntu:latest 
  script:
  - export DOCKER_HOST=tcp://docker:2375
  - docker version

Gitlab 好像没有为自定义图片设置 DOCKER_HOST 变量。

【讨论】:

【参考方案2】:

Gitlab CI 运行器需要挂载主机 docker 套接字才能在 docker 中执行 docker。例如:

docker exec gitlab-runner gitlab-runner register \
           --non-interactive \
           --url https://gitlab.com/ci \
           --registration-token TOKEN\
           --description "Docker Runner" \
           --tag-list "docker" \
           --executor docker \
           --docker-image "docker:latest" \
           --docker-volumes /var/run/docker.sock:/var/run/docker.sock

如您所见,docker.sock 作为最后一个参数安装在此处。但是我不建议在 Gitlab CI 中使用 docker-compose,因为 Gitlab CI 有自己的语法 https://docs.gitlab.com/ce/ci/docker/using_docker_images.html

【讨论】:

几件事 - 首先,我无法控制 gitlab-runner,因为我使用的是免费层 DigitalOcean 服务器。我(基本上)可以控制的只是我的.gitlab-ci.yml 中的内容。我将尝试重新构建我的构建设置以避免docker-compose,但是本地构建和 GitLab 构建使用相同的撰写文件/进程非常好。否则,.gitlab-ci,ymldocker-compose.yml 中的内容都会重复,例如我的 MySQL 实例、我的 Redis 实例等。 虽然我熟悉将docker.sock 作为卷安装到来宾容器,但它并不能完全解释docker:latest 容器如何能够访问dind 服务,而我的ubuntu:latest 图像不是。当我在docker:latest 容器内运行docker 命令时,它是否与我的dind 服务通信?

以上是关于从 GitLab CI 运行器连接到 docker-in-docker的主要内容,如果未能解决你的问题,请参考以下文章

为啥我无法从本地主机上的 Gitlab CI 连接到我的 docker-compose 服务

来自共享 Gitlab 运行器的 SSH 停止工作

如何设置GitLab +运行器来缓存Docker层

每次启动新构建时 RSA 指纹更改

gitlab-ci 注册运行器 x509

如何使用彼此独立的不同运行器运行 Gitlab CI 作业?