将 Jenkins 作为容器化服务运行并不是一项艰巨的任务。有许多图像可以让您做到这一点。我只花了几分钟就让 Jenkins 2.0-beta-1 在容器中运行,从源代码编译(图片可以在 here 找到)。特殊性 我喜欢这种方法,您只需要确保使用数据卷或数据容器作为jenkins_home 来使您的数据持久化。
当您想在容器中使用这个 Jenkins 来构建和管理容器本身时,事情变得有点棘手。为此,您需要实现一个名为 docker-in-docker 的东西,因为您需要 Jenkins 容器内的 docker 守护进程和客户端。
有一个很好的教程解释了如何做到这一点:Docker in Docker with Jenkins and Supervisord。
基本上,您需要使用 supervisord 之类的东西让两个进程(Jenkins 和 Docker)在容器中运行。它是可行的,并声称具有良好的隔离性,等等......但可能真的很棘手,因为 docker 守护进程本身有一些依赖项,这些依赖项也需要存在于容器中。因此,仅使用 supervisord 并运行两个进程是不够的,您需要利用 DIND 项目本身来使其工作......并且您需要以特权模式运行容器......并且您需要处理一些奇怪的 DNS 问题...
就我个人的喜好而言,让一些简单的事情工作起来听起来有太多的变通方法,并且在一个容器中运行两个服务似乎违反了 docker 的良好实践和关注点分离的原则,这是我想避免的。
当我读到这篇文章时,我的观点变得更加强烈:Using Docker-in-Docker for your CI or testing environment? Think twice。值得一提的是,这最后的帖子是来自DIND作者本人,所以他值得关注。
我的最终解决方案是:将 Jenkins 作为容器化服务运行,是的,但考虑将 docker 守护进程作为底层服务器配置的一部分,即使您的 docker 缓存和图像是您可能想要持久保存的数据,并且它们完全由守护进程拥有和控制。
有了这个设置,你需要做的就是在你的 Jenkins 镜像中挂载 docker daemon socket(它也需要 docker 客户端,但不需要服务):
$ docker run -p 8080:8080 -v /var/run/docker.sock:/var/run/docker.sock -v local/folder/with/jenkins_home:/var/jenkins_home namespace/my-jenkins-image
或者使用 docker-compose volumes 指令:
---
version: '2'
services:
jenkins:
image: namespace/my-jenkins-image
ports:
- '8080:8080'
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- local/folder/with/jenkins_home:/var/jenkins_home
# other services ...