docker 中的 Jenkins 可以访问主机 docker

Jenkins in docker with access to host docker

我有一个如下的工作流程,用于将 web 应用程序发布到我的开发服务器。服务器只有一个 docker 主机,我正在使用 docker-compose 来管理容器。

  1. 将我的应用程序中的更改推送到私有 gitlab(运行ning 在 docker 中)。该应用程序包含一个 Dockerfile 和 docker-compose.yml
  2. Gitlab 触发 jenkins 构建(jenkins 也在 docker 中 运行ning),它会做一些正常的构建工作(例如 运行 测试)
  3. Jenkins 然后需要构建一个新的 docker 镜像并使用 docker-compose 部署它。

我遇到的问题是在第 3 步。按照我设置的方式,jenkins 容器可以访问主机 docker,因此 运行 可以执行任何 docker 命令在构建脚本中与在主机上 运行ning 基本相同。这是为詹金斯使用以下 DockerFile 完成的:

FROM jenkins
USER root

# Give jenkins access to docker
RUN groupadd -g 997 docker
RUN gpasswd -a jenkins docker

# Install docker-compose
RUN curl -L https://github.com/docker/compose/releases/download/1.2.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
RUN chmod +x /usr/local/bin/docker-compose

USER jenkins

并将以下卷映射到 jenkins 容器:

-v /var/run/docker.sock:/var/run/docker.sock
-v /usr/bin/docker:/usr/bin/docker

jenkins 中的典型构建脚本如下所示:

docker-compose build
docker-compose up

这工作正常,但有两个问题:

我不太确定我在寻找什么解决方案。我看不出有任何实用的方法来绕过这种方法,但是如果有一种方法可以在 jenkins 容器中允许 运行ning docker 命令而不必在 GID 中硬编码Docker 文件。有人对此有什么建议吗?

我运行遇到同样的问题。由于 GID 问题,我最终给了 Jenkins 无密码 sudo 权限。我在这里写了更多相关内容:https://blog.container-solutions.com/running-docker-in-jenkins-in-docker

这不会真正影响安全性,因为拥有 docker 权限实际上等同于 sudo 权限。

请看一下我刚刚发布的 docker 文件: https://github.com/bdruemen/jenkins-docker-uid-from-volume/blob/master/gid-from-volume/Dockerfile

这里是从挂载的卷(主机目录)中提取的 GID,

stat -c '%g' <VOLUME-PATH>

然后将容器用户所在组的GID改为与

相同的值
groupmod -g <GID>

这必须以 root 身份完成,但随后 root 权限会被

删除
gosu <USERNAME> <COMMAND>

一切都在 ENTRYPOINT 中完成,所以真正的 GID 是未知的,直到你 运行

docker run -d -v <HOST-DIRECTORY>:<VOLUME-PATH> ...

请注意,更改 GID 后,进程可能无法再访问容器中的其他文件,因此您可能需要

chgrp -R <GROUPNAME> <SOME-PATH>    

在 gosu 命令之前。

您也可以更改 UID,请看我的回答Changing the user's uid in a pre-build docker container (jenkins) 也许您想更改两者以提高安全性。

我之前的回答比较笼统,告诉你如何在运行时修改容器内的 GID。现在,巧合的是,我的亲密同事中有人要求可以进行 docker 开发的 jenkins 实例,所以我创建了这个:

FROM bdruemen/jenkins-uid-from-volume
RUN apt-get -yqq update && apt-get -yqq install docker.io && usermod -g docker jenkins
VOLUME /var/run/docker.sock
ENTRYPOINT groupmod -g $(stat -c "%g" /var/run/docker.sock) docker && usermod -u $(stat -c "%u" /var/jenkins_home) jenkins && gosu jenkins /bin/tini -- /usr/local/bin/jenkins.sh

(父 Dockerfile 与我在回答中描述的相同:Changing the user's uid in a pre-build docker container (jenkins)

要使用它,请安装 jenkins_home 和 docker.sock。

docker run -d /home/jenkins:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock <IMAGE>

容器中的jenkins进程会和挂载的主机目录拥有相同的UID。假设主机上的 docker 组可以访问 docker 套接字,则在容器中创建了一个组,也名为 docker,具有相同的 GID。