迟到总比不到好。 或者我们几乎犯了一个严重的错误,因为不支持常规 Dockerfile 来构建应用程序映像。
我们将讨论
- 收集并发布图像,
- 在 Kubernetes 中部署应用程序,
- 使用特殊策略删除未使用的图像。
该项目的理念是将低级工具收集到一个统一的系统中,使 DevOps 工程师能够控制应用程序。 如果可能,应使用现有实用程序(例如 Helm 和 Docker)。 如果问题无法解决,我们可以为此创造并支持一切必要的东西。
背景:您自己的图像收集器
这就是 werf 中图像收集器发生的情况:通常的 Dockerfile 对我们来说不够。 如果你快速浏览一下该项目的历史,就会发现这个问题已经出现在 werf 的第一个版本中(然后仍然存在)
在创建用于将应用程序构建到 Docker 映像中的工具时,我们很快意识到 Dockerfile 不适合我们执行一些非常具体的任务:
- 需要按照以下标准方案构建典型的小型Web应用:
- 安装系统范围的应用程序依赖项,
- 安装一组应用程序依赖库,
- 收集资产,
- 最重要的是,快速高效地更新镜像中的代码。
- 当对项目文件进行更改时,构建者必须通过对更改的文件应用补丁来快速创建新层。
- 如果某些文件发生了变化,那么就需要重建相应的依赖阶段。
今天,我们的收藏家还有许多其他的可能性,但这些都是最初的愿望和冲动。
一般来说,我们不假思索地用我们所使用的编程语言武装自己 (见下文) 并踏上实施之路 自己的DSL! 根据目标,旨在分阶段描述组装过程并确定这些阶段对文件的依赖性。 并对其进行了补充 自己的收藏家,这将DSL变成了最终目标——组装图像。 起初 DSL 是用 Ruby 编写的,但随着
Ruby 中 dapp 的旧配置
YAML 上 werf 的当前配置
随着时间的推移,收集器的机制也发生了变化。 首先,我们只是根据配置动态生成一个临时 Dockerfile,然后开始在临时容器中运行汇编指令并提交。
NB:目前,我们的收集器使用自己的配置(在 YAML 中),称为 Stapel 收集器,已经发展成为一个相当强大的工具。 其详细描述值得单独撰写文章,基本细节可以在
对问题的认识
但我们并没有立即意识到我们犯了一个错误:我们没有添加这种能力 通过标准 Dockerfile 构建镜像 并将它们集成到相同的端到端应用程序管理基础设施中(即收集图像、部署和清理它们)。 怎么可能制作一个在 Kubernetes 中部署的工具而不实现 Dockerfile 支持,即描述大多数项目图像的标准方法?...
我们不回答这个问题,而是提供一个解决方案。 如果您已经有一个 Dockerfile(或一组 Dockerfile)并且想要使用 werf,该怎么办?
NB:顺便问一下,你为什么要使用 werf? 主要特点如下:
- 完整的应用程序管理周期,包括图像清理;
- 能够通过单个配置同时管理多个图像的组合;
- 改进了 Helm 兼容图表的部署流程。
更完整的列表可以在以下位置找到:
因此,如果早些时候我们愿意在配置中重写 Dockerfile,那么现在我们会很高兴地说:“让 werf 构建您的 Dockerfile!”
如何使用?
该功能的完整实现出现在发行版中 werf build
...就是这样 - werf 将组装图像。 让我们看一个抽象的例子。
让我们宣布下一篇 Dockerfile
在项目根目录中:
FROM ubuntu:18.04
RUN echo Building ...
我们将宣布 werf.yaml
它使用这个 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
最后,它还支持传递额外的构建参数,例如 --build-arg
и --add-host
- 通过werf配置。 Dockerfile 映像配置的完整描述可在以下位置找到:
它是如何工作的呢?
在构建过程中,Docker 中本地层的标准缓存发挥作用。 然而,重要的是 werf 也 将 Dockerfile 配置集成到其基础设施中。 这是什么意思?
- 从 Dockerfile 构建的每个映像都包含一个称为
dockerfile
(您可以阅读更多有关 werf 中的阶段的信息这里 ). - 舞台用
dockerfile
werf 计算取决于 Dockerfile 配置内容的签名。 当 Dockerfile 配置更改时,阶段签名会更改dockerfile
werf 使用新的 Dockerfile 配置启动此阶段的重建。 如果签名没有改变,则werf从缓存中获取图像 (有关在 werf 中使用签名的更多详细信息,请参见这份报告 ). - 接下来,可以使用命令发布收集到的图像
werf publish
(werf build-and-publish
)并使用它来部署到 Kubernetes。 发布到 Docker 注册表的镜像将使用标准 werf 清理工具进行清理,即旧镜像(超过 N 天)、与不存在的 Git 分支关联的镜像以及其他策略将被自动清理。
有关此处描述的要点的更多详细信息可以在文档中找到:
注意事项及注意事项
1.ADD不支持外部URL
目前不支持在指令中使用外部 URL ADD
。 当指定 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 收集器完美地完成了它的任务。
然而,在编写我们自己的构建器的过程中,我们忽略了对现有 Dockerfile 的支持。 这个缺陷现已修复,将来我们计划开发 Dockerfile 支持以及我们的自定义 Stapel 构建器,用于分布式组装和使用 Kubernetes 进行组装(即在 Kubernetes 内的运行器上进行组装,如 kaniko 中所做的那样)。
所以,如果你突然有几个 Dockerfile ...... 尝试
PS 有关该主题的文档列表
-
快速入门指南 ; -
dockerfile 构建器配置 ; -
werf 中的阶段设备 ; -
图片发布流程 ; -
与 Kubernetes 部署流程集成 ; -
清洗工艺 ; -
Stapel 构建器作为 Dockerfile 的替代品 .
另请阅读我们的博客:“
来源: habr.com