构建派生容器
规范
这是 openSUSE 发行版中所有容器镜像的规范。如果您在 OBS 的个人项目或非用于提交到 openSUSE 发行版的开发项目中构建镜像,则它们不需要遵循此规范。
正在努力在构建期间检查大多数规则。一旦激活,任何违反规则的情况都将在构建期间报告,并且在 `openSUSE:` 项目中导致构建失败。
本文档中使用了许多术语,这些术语指的是容器镜像的各个部分。
namespace tag
|-------| |----|
registry.opensuse.org/foo/bar/baz:latest
|--------------------|-----------|
registry repository
|--------------------------------------|
reference
构建工具的选择
容器镜像必须使用 KIWI 配方或 Dockerfile(使用 podman 构建)构建。
每种方法都有其自身的优点和缺点。Kiwi 支持使用主机/构建系统的软件包管理器,因此它可以构建基本镜像并派生不包含软件包管理器的镜像,例如 `opensuse/busybox`。使用 Dockerfile,实际上需要使用完整的基本镜像,例如 `opensuse/tumbleweed`。
通用规则
- 提交的名为 `foo-image` 的镜像需要包含匹配的 `foo.changes` 文件
- 不允许直接引用仓库(使用 `obsrepositories:/` 可以)
- 在使用 kiwi 时,用于提交的软件包名称和 `.kiwi` 文件中的 `
` 属性必须相同 - 构建配方和附带文件必须在 OSI 批准的许可下。完整的许可文本必须包含在一个单独的文件中。
镜像名称
从 OBS 的 `openSUSE:Containers` 子项目发布的所有镜像在 registry.opensuse.org 上可见,其仓库和标签由这些镜像定义(参见标签 (Tagging))。与 home: 和 devel 项目不同,没有基于项目和(构建)仓库名称的强制前缀。
由于每个镜像都可以自由定义其在注册表中的位置,因此重要的是它们之间进行协调和协作。这主要是为了避免冲突和混淆,但也为了确保一致性,因为这些引用是公开可见的。
由于 `registry.opensuse.org` 在官方发布的镜像和 devel 和 home 项目的任意镜像之间共享,因此必须特别注意,以便轻松辨别特定镜像是否来自官方来源。目前,这是通过保留不与非官方项目重叠的特殊前缀来实现的:`opensuse/`、`kubic/` 和 `kubevirt/`。
虽然仓库和标签名称可以是任何有效的 OCI 标识符,但外部工具施加了一些限制
- docker 默认使用 Docker Hub 作为注册表(硬编码!),任何人都可以上传镜像。选择的仓库名称未在 Docker Hub 上分配是有益的,否则可能会意外使用。Docker Hub 上的 `opensuse/` 前缀(例如,用于基本容器)为空,因此没有歧义。
- 一些注册表不支持根目录中的仓库(`registry.opensuse.org/foo:latest`)或嵌套命名空间(`registry.opensuse.org/asdf/bar/baz:latest`)。后者最近已不再成为一个问题。
- 仓库名称也不能用作命名空间,例如(`registry.opensuse.org/some/container:latest` 和 `registry.opensuse.org/some/container/withstuff:latest`),这意味着例如 `opensuse/tumbleweed/httpd` 是不可能的。
软件包名称
软件包名称(例如 `opensuse-tumbleweed-image`)必须以 `image` 或 `container` 结尾,并且与主镜像名称相关。对于 `opensuse/hello-world`,匹配的软件包名称将是 `opensuse-hello-world-image` 或 `hello-world-container`。
标签
标签可以自由定义。在每次发布新的构建(Tumbleweed Snapshot、Leap 镜像构建)时,新的构建都会发布到 `openSUSE:Container` 的子项目中,旧镜像会被保留。如果多个镜像提供了一个标签,则使用最新的镜像。
必须有一个标签,该标签仅由特定的构建提供。只能通过包含完整的版本(包括构建计数器)来实现。
在使用 kiwi_metainfo_helper 服务时,可以将其表示为例如:
#!BuildTag: opensuse/example:1.0 opensuse/example:1.0.%RELEASE%
此标签是必须在 `org.opensuse.reference` 标签中使用的标签。
标签 (Labels)
使用 Docker 标签的一个缺点(我们需要它来实现兼容性)是镜像中只有一个级别的标签,而不是每个层一个。这意味着基本容器中定义的标签可以被派生镜像中的标签覆盖。未被覆盖的标签不会显示来自基本容器。
为了解决这个问题,必须将特定信息克隆到带有 `org.opensuse.
| 标签 (Label) | OCI 注释 | 派生镜像必须提供 | 描述 | 示例 |
|---|---|---|---|---|
| org.opencontainers.image.title org.opensuse.base.title | org.opencontainers.image.title | 是 | 镜像标题 | openSUSE Tumbleweed 基本容器
|
| org.opencontainers.image.description org.opensuse.base.description | org.opencontainers.image.description | 是 | 镜像的简短描述 | 包含基于 openSUSE Tumbleweed 的容器的最小环境的镜像。
|
| org.opencontainers.image.version org.opensuse.base.version | org.opencontainers.image.version | 是 | 镜像版本。<version>.<cicnt>.<bldcnt> | 20181224.4.2
|
| org.opencontainers.image.created org.opensuse.base.created | org.opencontainers.image.created | 是 | 镜像构建日期/时间 | 2019-01-05T14:12:30Z
|
| org.opencontainers.image.vendor org.opensuse.base.vendor | org.opencontainers.image.vendor | 否 | 镜像供应商 | openSUSE Project
|
| org.opencontainers.image.url org.opensuse.base.url | org.opencontainers.image.url | 否 | 包含更多信息的 URL | https://opensuse.net.cn/
|
| org.openbuildservice.disturl org.opensuse.base.disturl | org.openbuildservice.disturl | 是 | OBS 提供的分发 URL | obs://build.opensuse.org/openSUSE:Factory/images/4985c42063a1f194292ecb777d41923b-opensuse-tumbleweed-image:docker
|
| org.opensuse.reference org.opensuse.base.reference | org.opensuse.reference | 是 | 指向此特定镜像的引用(`registry.opensuse.org/imagename[:tag]`) | registry.opensuse.org/opensuse/tumbleweed:20181224.4.2
|
历史
每个镜像都应定义一个历史记录条目,其中包含对该镜像的易于理解的描述。这样可以轻松了解镜像中的每一层是什么。
> docker history opensuse/tumbleweed IMAGE CREATED CREATED BY SIZE COMMENT aaa05880bad2 2 days ago KIWI 9.17.15 123MB openSUSE Tumbleweed 20190312 Base Container
入门
开始构建新容器镜像的最简单方法是使用预定义的模板并提交它们。
分支模板
在 OBS 主页上,有一个链接到 可用模板的概述。“使用 Dockerfile/KIWI 的应用程序容器”和“使用 KIWI 的派生容器”模板可用于提交到 openSUSE 发行版。如果您单击模板的标题,可以四处查看并找出最适合您的模板
根据您的工具选择,选择要构建的发行版的适当模板。确保分支到尚不存在的项目,否则镜像将无法构建。如果目标项目已经设置为针对您选择的发行版构建镜像,例如之前分支到该项目,那也可以。
调整构建配方文件
每个模板都有一个 README 文件,其中包含模板内部的特定说明。
添加 .changes 文件
可以使用 Web UI 创建匹配软件包名称的 `foo.changes` 文件并创建一个条目,或者在 OSC 结账中运行 `osc vc foo.changes`。第一个 changelog 条目应包含对镜像的简短描述。
添加 README
此步骤不是必需的,但建议用于具有自定义入口点的镜像。有关如何使用镜像及其接受的变量的文档应在此处。
测试
在启用 OBS 上软件包(或整个项目)的发布后,可以通过 registry.opensuse.org 访问该镜像。您可以使用 docker 和 podman 下载它,请参阅 注册表概述页面。
位置是 OBS 上的项目名称,其中 ':' 替换为 '/',并附加了仓库(KIWI:`images`,Dockerfile:`containers`)。例如,https://build.opensuse.org/package/show/openSUSE:Templates:Images:Tumbleweed/dockerfile-application-container 构建 `opensuse/example:latest` 并且可用作
registry.opensuse.org/opensuse/templates/images/tumbleweed/containers/opensuse/example:latest
提交
可以将容器镜像提交到 `openSUSE:Factory` 和 `openSUSE:Leap:15.1` 及更高版本。对于 Leap,可以通过提交维护更新来引入新镜像。
提交到发行版的常用规则适用,因此需要选择一个 devel 项目并将其用作提交基础。
有用的 OBS 服务
多个 OBS 服务通过简化标签定义和版本控制等过程来帮助实施规范。
它们在 _service 文件中添加和配置(请参阅模板中的示例),并在构建开始之前运行各种脚本。
Dockerfile + KIWI: obs-service-kiwi_metainfo_helper
为了能够在标签和标签中包含构建时信息(例如当前构建编号),此服务会替换配方文件中的某些占位符。它适用于 .kiwi 和 Dockerfile 配方。
更新的占位符列表及其内容在软件包本身中,您可以在 此处 阅读。
KIWI only: obs-service-kiwi_label_helper
为了更容易地定义 “org.opensuse.
README 的副本
此服务可以在构建时运行,此时它将编辑 kiwi 镜像描述以扩展 `<suse_label_helper:add_prefix/>` 元素。
示例
<image [...] xmlns:suse_label_helper="com.suse.label_helper">
[...]
<containerconfig [...]>
<labels>
<suse_label_helper:add_prefix prefix="org.opensuse.base">
<label name="org.opencontainers.image.title" value="openSUSE Tumbleweed Base Container"/>
</suse_label_helper:add_prefix>
扩展到
<image [...] xmlns:suse_label_helper="com.suse.label_helper">
[...]
<containerconfig [...]>
<labels>
<label name="org.opencontainers.image.title" value="openSUSE Tumbleweed Base Container"/>
<label name="org.opensuse.base.title" value="openSUSE Tumbleweed Base Container"/>
Dockerfile only: obs-service-docker_label_helper
为了更容易地定义 “org.opensuse.
有关详细信息,请参阅 README。
使用 KIWI 的技巧
标签 (Tagging)
KIWI 支持 `additionaltags` 属性,OBS 服务(例如 obs-service-kiwi_metainfo_helper)可以将构建时信息添加到标签中。
<preferences>
<type image="docker">
<containerconfig
name="opensuse/leap"
tag="15.0.%RELEASE%"
additionaltags="15.0"
maintainer="Fabian Vogt <fvogt@suse.com>">
<labels>
使用 Dockerfile 的技巧
标签 (Tagging)
Dockerfile 配方没有关于应如何命名构建镜像的信息,这在 `docker/podman build` 手动构建镜像时传递。OBS 从 Dockerfile 中的特殊注释中获取此信息,例如:
#!BuildTag: opensuse/example:1.0 opensuse/example:latest
可以在同一个 `BuildTag` 注释中提及多个名称,或者添加多个此类注释。
发布机制
容器在 `openSUSE:Factory` 和 `openSUSE:Leap:15.x:Images` 中与其他镜像一起构建。`OSRT:ToTestManagerConfig` 属性中的列表,用于每个项目,告诉 totest-manager 机器人哪些构建的镜像是容器镜像,应该发布到注册表而不是下载服务器。
这些镜像发布到 `containers` repo 的 `ToTest` 子项目,在那里它们被推送到 `registry.opensuse.org`,openQA 可以从那里下载和测试它们。这是由 “image”测试模块 完成的,该模块针对多个容器运行时(docker、podman、...)实例化。
在 openQA 将快照/构建标记为良好后,ttm 会将容器从 `ToTest/containers` 发布到其 releasetarget。对于 `openSUSE:Factory:ToTest/containers`,那是 `openSUSE:Containers:Tumbleweed`。这些目标项目在其元数据中设置了 `kind="maintenance_release"`,因此每次发布都会添加二进制文件而不是覆盖它们。这意味着在 OBS 和注册表中可用所有发布的(且未清理的)容器。
对于注册表中的每个 repo(例如 `opensuse/tumbleweed` 和 `kubic/pause`),OBS 中只有一个项目/repo 组合提供向这些 repo 馈送镜像。目前,这对于 Tumbleweed 和 Kubic 来说不是问题,但由于 Leap 的所有版本共享一个 repo,但镜像分布在多个项目(`openSUSE:Containers:Leap:15.x`)上,因此必须解决这个问题。这是通过在 `openSUSE:Containers:Leap` 创建一个中间项目来实现的,该项目聚合最终进入注册表 `opensuse/leap` repo 中的所有二进制文件。原始项目本身被禁用发布,以使其正常工作。
为了提供动态的 `opensuse/leap:latest` 和 `opensuse/leap:15` 标签,这些标签如 项目配置 中所述添加到聚合中。