Chisel
Chisel是一个用于裁剪和切割Debian软件包的工具!
它基于软件包切片的概念 - 这些切片是最小的、互补的、松耦合的文件集合,基于软件包的元数据和内容。切片本质上是Debian软件包的子集,具有自己的内容和对其他内部和外部切片的依赖集。
这张图描述了一个简单的情况,其中软件包A和B都被分解成多个切片。在软件包层面,B依赖于A,但实际上,A中可能有一些B并不真正需要的文件(例如,B的正常运行不需要A_slice3)。有了这种切片定义,Chisel能够提取高度定制和专门化的Ubuntu发行版切片,可以将其视为一块石头,我们可以从中雕刻和提取运行应用程序所需的小而相关的部分。这非常适合用于创建更小但功能同样完整的容器镜像。
"雕塑在我开始工作之前就已经完整地存在于大理石块中。它已经在那里了,我只需要凿掉多余的材料。"
- 米开朗基罗
最终,这就像拥有一片Ubuntu - 只获取你所需要的。你可以鱼和熊掌兼得!
使用Chisel
要安装最新版本的Chisel,请运行以下命令:
go install github.com/canonical/chisel/cmd/chisel@latest
Chisel通过chisel <命令>
来调用。要获取更多信息:
- 要查看帮助摘要,请输入
chisel -h
。 - 要查看所有命令的简短描述,请输入
chisel help --all
。 - 要查看某个命令的详细信息,请输入
chisel help <命令>
或chisel <命令> -h
。
示例命令
Chisel依赖于一个切片数据库,该数据库按Ubuntu版本进行索引。
chisel cut --release ubuntu-22.04 --root myrootfs/ libgcc-s1_libs libssl3_libs
在这个例子中,Chisel会查找Ubuntu Jammy存档,获取提供的软件包,并根据"ubuntu-22.04" chisel-releases分支中可用的切片定义,仅将所需的切片安装到myrootfs文件夹中。
参考
Chisel发布
如上所述,Chisel依赖于软件包切片。这些切片需要在执行chisel
命令之前定义。
默认情况下,Chisel会查找其中央chisel-releases数据库,其中软件包切片按Ubuntu版本定义和索引。发布版本由分支名称标识。例如:
chisel cut --release ubuntu-22.10 ...
将告诉Chisel在chisel-releases仓库的"ubuntu-22.10"分支中查找chisel.yaml
文件。这个文件将指示Chisel从相应的Ubuntu存档的Kinetic发布中获取所请求的软件包切片,这些切片在同一分支中定义。
另外,也可以通过指定路径而不是分支名称来让Chisel指向自定义的本地Chisel发布。例如:
chisel cut --release release/ ...
Chisel发布配置
每个Chisel发布必须有一个"chisel.yaml"文件。
chisel.yaml:
format: <chiselReleaseFormat>
archives:
ubuntu:
# Chisel要查找的Ubuntu存档
version: <ubuntuRelease>
# 要查找的Ubuntu存档的类别/组件
components: [<componentName>, ...]
# 要查找的Ubuntu存档的pocket/套件
suites: [<pocket>, ...]
示例:
format: v1
archives:
ubuntu:
version: 22.04
components: [main, universe]
suites: [jammy, jammy-security, jammy-updates]
public-keys: [ubuntu-archive-key-2018]
public-keys:
# Ubuntu Archive Automatic Signing Key (2018) <ftpmaster@ubuntu.com>
# rsa4096/f6ecb3762474eda9d21b7022871920d1991bc93c 2018-09-17T15:01:46Z
ubuntu-archive-key-2018:
id: "871920D1991BC93C"
armor: |
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBFufwdoBEADv/Gxytx/LcSXYuM0MwKojbBye81s0G1nEx+lz6VAUpIUZnbkq
dXBHC+dwrGS/CeeLuAjPRLU8AoxE/jjvZVp8xFGEWHYdklqXGZ/gJfP5d3fIUBtZ
HZEJl8B8m9pMHf/AQQdsC+YzizSG5t5Mhnotw044LXtdEEkx2t6Jz0OGrh+5Ioxq
X7pZiq6Cv19BohaUioKMdp7ES6RYfN7ol6HSLFlrMXtVfh/ijpN9j3ZhVGVeRC8k
KHQsJ5PkIbmvxBiUh7SJmfZUx0IQhNMaDHXfdZAGNtnhzzNReb1FqNLSVkrS/Pns
AQzMhG1BDm2VOSF64jebKXffFqM5LXRQTeqTLsjUbbrqR6s/GCO8UF7jfUj6I7ta
LygmsHO/JD4jpKRC0gbpUBfaiJyLvuepx3kWoqL3sN0LhlMI80+fA7GTvoOx4tpq
VlzlE6TajYu+jfW3QpOFS5ewEMdL26hzxsZg/geZvTbArcP+OsJKRmhv4kNo6Ayd
yHQ/3ZV/f3X9mT3/SPLbJaumkgp3Yzd6t5PeBu+ZQk/mN5WNNuaihNEV7llb1Zhv
Y0Fxu9BVd/BNl0rzuxp3rIinB2TX2SCg7wE5xXkwXuQ/2eTDE0v0HlGntkuZjGow
DZkxHZQSxZVOzdZCRVaX/WEFLpKa2AQpw5RJrQ4oZ/OfifXyJzP27o03wQARAQAB
tEJVYnVudHUgQXJjaGl2ZSBBdXRvbWF0aWMgU2lnbmluZyBLZXkgKDIwMTgpIDxm
dHBtYXN0ZXJAdWJ1bnR1LmNvbT6JAjgEEwEKACIFAlufwdoCGwMGCwkIBwMCBhUI
AgkKCwQWAgMBAh4BAheAAAoJEIcZINGZG8k8LHMQAKS2cnxz/5WaoCOWArf5g6UH
beOCgc5DBm0hCuFDZWWv427aGei3CPuLw0DGLCXZdyc5dqE8mvjMlOmmAKKlj1uG
g3TYCbQWjWPeMnBPZbkFgkZoXJ7/6CB7bWRht1sHzpt1LTZ+SYDwOwJ68QRp7DRa
Zl9Y6QiUbeuhq2DUcTofVbBxbhrckN4ZteLvm+/nG9m/ciopc66LwRdkxqfJ32Cy
q+1TS5VaIJDG7DWziG+Kbu6qCDM4QNlg3LH7p14CrRxAbc4lvohRgsV4eQqsIcdF
kuVY5HPPj2K8TqpY6STe8Gh0aprG1RV8ZKay3KSMpnyV1fAKn4fM9byiLzQAovC0
LZ9MMMsrAS/45AvC3IEKSShjLFn1X1dRCiO6/7jmZEoZtAp53hkf8SMBsi78hVNr
BumZwfIdBA1v22+LY4xQK8q4XCoRcA9G+pvzU9YVW7cRnDZZGl0uwOw7z9PkQBF5
KFKjWDz4fCk+K6+YtGpovGKekGBb8I7EA6UpvPgqA/QdI0t1IBP0N06RQcs1fUaA
QEtz6DGy5zkRhR4pGSZn+dFET7PdAjEK84y7BdY4t+U1jcSIvBj0F2B7LwRL7xGp
SpIKi/ekAXLs117bvFHaCvmUYN7JVp1GMmVFxhIdx6CFm3fxG8QjNb5tere/YqK+
uOgcXny1UlwtCUzlrSaP
=9AdM
-----END PGP PUBLIC KEY BLOCK-----
切片定义
每个Chisel发布版本中,每个Ubuntu软件包只能有一个切片定义文件。所有切片定义文件必须放在"slices"文件夹下,并遵循相同的结构。例如:
slices/B.yaml:
# (必需) 软件包的名称。
# 切片定义文件应相应命名(例如:"openssl.yaml")
package: B
# (必需) 切片列表
slices:
# (必需) 切片的名称
slice2:
# (可选)此切片依赖的其他切片列表
essential:
- A_slice1
# (必需)此切片将安装的包中的文件列表
contents:
/path/to/content:
/path/to/another/multiple*/content/**:
/path/to/moved/content: {copy: /bin/original}
/path/to/link: {symlink: /bin/mybin}
/path/to/new/dir: {make: true}
/path/to/file/with/text: {text: "Some text"}
/path/to/mutable/file/with/default/text: {text: FIXME, mutable: true}
/path/to/temporary/content: {until: mutate}
# (可选)变异脚本,用于重现维护者脚本,
# 基于Starlark(https://github.com/google/starlark-go)
mutate: |
foo = content.read("/path/to/temporary/content")
content.write("/path/to/mutable/file/with/default/text", foo)
示例:
package: mypkg
slices:
bins:
essential:
- mypkg_config
contents:
/bin/mybin:
/bin/moved: {copy: /bin/original}
/bin/linked: {symlink: /bin/mybin}
config:
contents:
/etc/mypkg.conf: {text: "The configuration."}
/etc/mypkg.d/: {make: true}
要查找更多真实切片定义文件的示例(并贡献您自己的), 请访问https://github.com/canonical/chisel-releases。
路径类型
如上例所示,切片内容下列出的路径可以包含额外信息来标识预期的内容类型:
- make:一个
true
或false
布尔值,用于指定是否必须创建该路径。 示例:/etc/mypkg.d/: {make: true}
指示Chisel创建"/etc/mypkg.d/"目录(包括父目录)。 注意:为使make
有效,提供的路径必须以"/"结尾。 - mode:一个32位无符号整数,表示路径模式。
示例:
/etc/dir/sub/: {make: true, mode: 01777}
指示Chisel以"01777"模式创建"/etc/dir/sub/"目录。 - copy:一个字符串,指向被复制内容的原始路径。
示例:
/bin/moved: {copy: /bin/original}
指示Chisel将包中的"/bin/original"文件复制到"/bin/moved"。 - text:要写入提供的文件路径的字符序列。
示例:
/tmp/file1: {text: data1}
将指示Chisel将"data1"写入文件"/tmp/file1"。 - symlink:一个字符串,指向被链接内容的原始路径(源)。
示例:
/bin/linked: {symlink: /bin/mybin}
将指示Chisel创建指向现有文件"/bin/mybin"的符号链接"/bin/linked"。 - mutable:一个
true
或false
布尔值,用于指定内容是否可变,即从deb中提取后是否可以更改。 示例:/tmp/file1: {text: data1, mutable: true}
指示Chisel用"data1"填充"/tmp/file1",同时让Chisel知道此文件的内容可以通过变异脚本进行修改。 - until:接受
mutate
值,表示指定的内容将在执行变异脚本后被Chisel删除。 示例:/tmp/file1: {text: data1, until: mutate}
指示Chisel在安装时用"data1"填充文件"/tmp/file1",但在执行切片的变异脚本后立即删除它。 注意:虽然此选项可以与通配符结合使用(例如/tmp/file*: {until: mutate}
),但不能用于删除非空目录。 - arch:接受已知架构列表,用于标识仅适用于某些架构的内容。
示例:
/usr/bin/hello: {arch: amd64}
将指示Chisel仅在制作amd64文件系统时提取并安装"/usr/bin/hello"文件。
待办事项
- 尽可能保留所有权
- 归档的GPG签名检查
- 为归档测试使用模拟服务器
- 功能测试
常见问题
我可以使用任意包名吗?
不可以,包名必须反映归档中的包名,以便有一个单一的命名空间来记住和遵守。
我尝试使用不同的Ubuntu版本,但失败了?
目前映射是手动的。请告诉我们,我们会修复它。
我可以在Chisel发布中使用多个仓库吗?
目前不行,但可能最终会支持。
我可以使用非Ubuntu仓库吗?
目前不行,但最终会支持。
多个切片可以引用相同的路径吗?
可以,但请参见下文。
多个切片可以_输出_相同的路径吗?
可以,只要这些切片属于同一个包,或者该路径根本不是从包中提取的(非复制),且显式内联定义完全匹配。
是否保留文件所有权?
目前不会,但将来会支持。