迟到总比没有好。 或者我们几乎犯了一个严重的错误,没有普通的Dockerfiles支持来构建应用程序映像。
我们将讨论
werf ,它是一个与任何CI / CD系统集成并提供对整个应用程序生命周期的控制的GitOps实用程序,使您能够:
- 收集并发布图像
- 在Kubernetes中部署应用程序
- 使用特殊策略删除未使用的图像。
该项目的理念是将低级工具组装到一个统一的系统中,从而使DevOps工程师可以控制应用程序。 在可能的情况下,应使用现有的实用程序(例如Helm和Docker)。 如果无法解决问题,我们可以创建并维护为此所需的一切。
背景:您的图像收集器
这是werf中的图像收集器发生的情况:我们没有通常的Dockerfile。 如果您快速投入到项目的历史中,那么这个问题就会在werf的第一个版本(当时仍
称为dapp )
中显现出来 。
通过创建用于在Docker映像中构建应用程序的工具,我们很快意识到Dockerfile不适合某些非常具体的任务:
- 需要根据以下标准方案构建典型的小型Web应用程序:
- 安装系统范围的应用程序依赖项
- 安装捆绑的应用程序依赖库,
- 收集资产
- 最重要的是,快速有效地更新图像中的代码。
- 对项目文件进行更改时,构建器必须通过将补丁应用到修改后的文件来快速创建新层。
- 如果某些文件已更改,则必须重建适当的依赖阶段。
今天,在我们的收藏家中,还有许多其他可能性,但是最初的愿望和冲动就是这些。
通常,无需三思而后行,我们就能使用所使用的编程语言武装自己
(见下文),并一路走上-实现
我们自己的DSL ! 与任务相对应,它旨在按阶段描述组装过程,并确定这些阶段对文件的依赖性。 在他
自己的收藏家的帮助下 ,他将DSL变成了最终目标-组合图像。 最初,DSL是在Ruby中进行的,当我们
切换到Golang时 ,收集器的配置开始在YAML文件中进行描述。
Ruby上dapp的旧配置
YAML上werf的当前配置收集器的机制也随着时间而改变。 首先,我们只是通过运行中的配置简单地生成了一个临时的临时Dockerfile,然后开始在临时容器中运行汇编指令并进行提交。
注意 :目前,我们的收集器已经可以发展成为一个功能非常强大的工具,该收集器使用其配置(在YAML中),并且称为Stapel-collector。 其详细说明应另作文章,主要细节可在文档中找到。问题意识
但是我们意识到并且没有立即意识到我们犯了一个错误:我们没有添加
通过标准Dockerfile收集映像并将其集成到用于集成应用程序管理的相同基础结构中的功能(即收集映像,部署和清理它们)。 您如何在Kubernetes中制作一个部署工具而不实现Dockerfile支持,即 一种描述大多数项目图像的标准方法?
我们没有回答这个问题,而是提供了解决方案。 如果您已经有一个Dockerfile(或一组Dockerfile)并想使用werf怎么办?
NB :顺便说一句,您为什么还要使用werf? 主要功能如下:- 完整的应用程序管理周期,包括图像清理;
- 从单个配置控制多个图像的组合的能力;
- 改进了与Helm兼容的图表部署过程。
在项目页面上可以找到它们的更完整列表。因此,如果早些时候我们建议将Dockerfile重写为我们的配置,现在现在我们将很高兴地说:“让我们来构建您的Dockerfile!”
使用方法
此功能的完整实现出现在
werf v1.0.3-beta.1版本中 。 一般原则很简单:用户在werf配置中指定现有Dockerfile的路径,然后运行
werf build
...命令,就是这样-werf将收集映像。 考虑一个抽象的例子。
在项目的根目录中
Dockerfile
以下
Dockerfile
:
FROM ubuntu:18.04 RUN echo Building ...
并声明使用此
Dockerfile
:
configVersion: 1 project: dockerfile-example --- image: ~ dockerfile: ./Dockerfile
仅此而已! 仍然
需要运行werf build
:

此外,您可以声明以下
werf.yaml
以便一次从不同的Dockerfile构建多个映像:
configVersion: 1 project: dockerfile-example --- image: backend dockerfile: ./dockerfiles/Dockerfile-backend --- image: frontend dockerfile: ./dockerfiles/Dockerfile-frontend
最后,它还支持通过werf配置传输其他构建参数,例如
--build-arg
和
--add-host
。
文档页面上提供了Dockerfile映像配置的完整说明。
如何运作?
在构建过程中,Docker中的标准本地层缓存起作用。 但是,重要的是,werf还将
Dockerfile配置集成到其基础架构中 。 这是什么意思?
- 从Dockerfile收集的每个映像都包含一个称为
dockerfile
阶段(有关werf中的各个阶段的更多信息,您可以在此处阅读)。 - 对于阶段,
dockerfile
werf计算签名,具体取决于Dockerfile配置的内容。 更改Dockerfile配置后, dockerfile
阶段签名dockerfile
并且werf使用新的Dockerfile配置启动此阶段的重建。 如果签名不变,则werf从缓存中获取图像( 此报告中介绍了有关在werf中使用签名的更多信息) 。 - 此外,可以
werf publish
命令werf publish
收集的图像(或werf build-and-publish
),并将其用于Kubernetes中的部署。 Docker Registry中发布的映像将使用标准的werf清理器清理,即 它将自动清除旧映像(早于N天),与不存在的Git分支关联的映像以及其他策略。
您可以从文档中了解有关此处描述的要点的更多信息:
注意事项及注意事项
1.不支持ADD中的外部URL
当前不支持在
ADD
指令中使用外部URL。 当资源更改为指定的URL时,Werf将不会启动重建。 计划很快添加此功能。
2.您不能将.git添加到图像
一般来说,在映像中添加
.git
目录是一种
恶性的坏习惯,原因如下:
- 如果
.git
保留在最终映像中,则违反了12因子应用程序的原理:由于最终映像必须与一个提交相关联,因此不可能对任意提交进行git checkout
。 .git
增加了图像的大小(由于曾经向其中添加大文件然后删除了大文件,因此存储库可能很大)。 仅与特定提交相关联的工作树的大小将不依赖于Git中的操作历史。 同时,从最终映像中添加然后删除.git
将不起作用:该映像仍将获得额外的一层-这就是Docker的工作方式。- Docker可以启动不必要的重建,即使正在构建相同的提交,但使用不同的工作树也是如此。 例如,启用并行汇编后,GitLab在
/home/gitlab-runner/builds/HASH/[0-N]/yourproject
创建单独的克隆目录。 额外的重建将归因于以下事实:即使收集了相同的提交,同一存储库的不同克隆版本中的.git
目录也不同。
最后一点在使用werf时会产生后果。 Werf要求在运行某些命令时(例如
werf deploy
)必须存在收集的缓存。 在执行此类命令期间,werf将为werf.yaml中指定的映像计算阶段签名,并且这些签名必须位于程序集缓存中-否则团队将无法继续工作。 如果阶段签名将取决于
.git
的内容,那么我们将获得一个对无关文件的更改不稳定的缓存,并且werf将无法原谅这种疏忽(请参阅
文档以获取更多详细信息)。
通常,在任何情况下,通过
ADD
指令
仅添加某些必需的文件都可以提高写入的
Dockerfile
的效率和可靠性,并且还可以提高此
Dockerfile
生成的缓存的稳定性,以防止Git的无关更改。
总结
我们为满足特定需求而编写自己的编译器的最初方法是困难,诚实和直接的:我们不是在标准Dockerfile之上使用拐杖,而是使用自定义语法编写了自己的解决方案。 这样做有其优点:Stapel-builder可以完美地完成其任务。
但是,在编写自己的收集器的过程中,我们忽略了现有Dockerfiles的支持。 现在,此缺陷已得到修复,并且将来我们计划与自定义Stapel收集器一起开发Dockerfile支持,以进行分布式装配和使用Kubernetes的装配(即在Kanbernetes内的转轮上进行装配,就像在kaniko中一样)。
因此,如果您突然在附近有几个Dockerfile,请
尝试werf !
PS相关文件清单
还要在我们的博客上阅读:“
werf是Kubernetes中的CI / CD工具(审阅和视频报告) 。”