1.容器镜像构建工具和方案介绍
如果你只是在单机本地构建镜像的话,使用docker build
或nerdctl+containerd+buildkit
确实没有问题,但实际
中由于不同场景和技术背景下的限制,如docker build
依赖于docker daemon
,这些限制使得在一些特殊的场景下
本机构建镜像的方式不再可用。
以cicd为列:
结合了容器技术,将Jenkins用于构建的Slave节点放到容器中,并基于K8S来动态调度管理这些Jenkins Slave容
器。这样一来Jenkins就具备了基于容器的分布式构建能力, 一个应用从源码经过各个阶段到最终的镜像是采用分布
式构建实现的,各个阶段也都是在容器中进行的。
分布式构建,首先要面对的问题就是要在jenkins slave容器的内部构建镜像。由于docker是以docker cli和docker daemon的C/S形式工作,如果把docker cli放到jenkins slave容器里面执行docker build,那么docker build所需的docker daemon放哪儿呢? 于是就有了Docker in Docker
和Docker outside of Docker
两种方案
1.1 Docker in Docker
Docker in Docker
简称DinD
。DinD模式是指在一个容器内部安装完整的docker服务,启动一个Docker
Daemon,然后就可以在容器内部使用docker cli进行镜像的构建。 此方案的优点是容器中的Docker Daemon与外
部完全隔离,隔离性较好,而缺点是容器内部比较臃肿复杂,同时要解决容器内docker服务的持久化存储、构建缓存
的问题,在安全上DinD还需要以特权(--privileged
)形式启动容器,有安全风险。 因此这种方案在实际好少使用,
也不推荐使用
。
1.2 Docker outside of Docker
Docker outside of Docker
简称DooD
。DooD模式是指将容器外部宿主机上的docker daemon的socket挂载到容
器内,让容器内的docker cli误认为本地启动了docker daemon,这样进行docker build等命令操作时由容器外
部宿主机上的docker daemon处理请求。 此方案的优点是容器内部不需要安装docker daemon,构建在宿主机上进
行效率较高,缺点是没有与外部隔离,构建的镜像与宿主机上的镜像存在冲突的可能,同一宿主机上不支持并行构建。
在早些年前使用DooD这种方案的人比较多。
1.3 Kaniko
Kaniko是Google开源的一款容器镜像构建工具,可以用来在容器中或者Kubernetes集群中进行镜像的构建。 在Kaniko出现之前,使用Dockerfile和Docker cli来构建镜像时,需要将构建的上下文发送至docker daemon,Docker in Docker和Docker outside of Docker也不例外。 Kaniko构建容器镜像时并不依赖于Docker daemon,也不需要特权权限,这一特性使得kaniko成为DinD或者DooD之外的一种全新的解决方案。
Kaniko构建容器镜像时,需要三个输入: Dockerfile,构建上下文,以及构建成功后镜像在仓库中的存放地址。 kaniko executor需要在容器执行,前面三个输入可以挂载到kaniko executor的容器中。
Kaniko支持多种方式将构建上下文挂载到容器中: 可以使用本地文件夹,GCS bucket,S3 bucket等等方式,使用GCS 或者 S3时需要把上下文压缩为tar.gz,kaniko会自行在构建时解压上下文。
Kaniko executor在找到Dockerfile后会逐条解析Dockerfile内容,并且执行相关的命令。在用户目录中形成容器镜像的文件层,每条Dockerfile中的指令都执行完毕后,Kaniko会将新生成的镜像推送到指定的镜像仓库中去。 整个过程中,完全不依赖于docker daemon。