☰
rkt 快速上手指南:构建 ACI 镜像并运行你的第一个容器化应用
2026/9/25 16:09:34 网站建设 项目流程
  • 容器运行时
  • 云原生
  • 网络

【免费下载链接】rkt

[Project ended] rkt is a pod-native container engine for Linux. It is composable, secure, and built on standards.

项目地址:https://gitcode.com/gh_mirrors/rk/rkt
点击查看免费下载

本篇指南以 rkt(App Container 规范的参考实现)为背景,带你从零开始体验完整的容器应用生命周期:编写一个自包含的 Go HTTP 应用、静态编译、用 acbuild 打包成 ACI(App Container Image)、本地启动并用curl验证,最后补齐签名、验证、信任与 Meta Discovery 分发这一整套安全发布链路。读完本文,你将掌握构建一个无外部依赖、可签名分发、可被 rkt 安全拉取运行的容器镜像的全部实战技能。

环境准备:Linux 与构建前提

rkt 运行于 Linux。如果你不在 Linux 环境,官方建议在 rkt 提供的 Vagrant 虚拟机内完成本指南中的全部操作。整个流程不依赖 Docker,而是围绕 App Container 规范)。

本指南的核心任务链路如下:

  1. 编写并静态编译一个 Go 应用;
  2. 使用acbuild将其打包为 ACI;
  3. 通过rkt run启动容器,用rkt list与curl验证服务;
  4. 使用 gpg 签名 ACI,通过 Meta Discovery 分发,并借助rkt trust建立信任后安全拉取运行。

第一步:编写一个 hello Go 应用

创建一个 HTTP 服务,它监听:5000端口,对每个请求打印来源地址并返回hello:

package main import ( "log" "net/http" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { log.Printf("request from %v\n", r.RemoteAddr) w.Write([]byte("hello\n")) }) log.Fatal(http.ListenAndServe(":5000", nil)) }

第二步:构建一个静态链接的 Go 二进制

为了让 ACI 不携带任何外部依赖,必须静态链接二进制。使用 Go 1.9 及以上的标准编译方式:

$ CGO_ENABLED=0 go build -ldflags '-extldflags "-static"'

如果你使用 gccgo 编译器,则改为:

$ go build -compiler gccgo -gccgoflags '-static'

继续之前务必确认产物确实是静态链接的。用file与ldd验证:

$ file hello hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped $ ldd hello not a dynamic executable

看到statically linked与not a dynamic executable,说明二进制已完全静态化,可以安全地封进 ACI。

第三步:用 acbuild 创建 ACI 镜像

acbuild是构建 ACI 的专用工具,可以从 containers/build 仓库的 release 页面下载。下面这组命令会生成一个名为hello-0.0.1-linux-amd64.aci的镜像,其中包含应用二进制与关键的镜像元数据:

acbuild begin acbuild set-name example.com/hello acbuild copy hello /bin/hello acbuild set-exec /bin/hello acbuild port add www tcp 5000 acbuild label add version 0.0.1 acbuild label add arch amd64 acbuild label add os linux acbuild annotation add authors "Carly Container <carly@example.com>" acbuild write hello-0.0.1-linux-amd64.aci acbuild end

上述每一步的含义:

  • set-name:为镜像命名。名称采用 URL 式结构,后续可用于 Meta Discovery 与按名拉取;
  • copy:把静态二进制放进镜像根文件系统的/bin/hello;
  • set-exec:声明容器启动时要执行的程序;
  • port add www tcp 5000:声明应用暴露的端口(www是端口名,协议为tcp,端口 5000);
  • label add version/arch/os:写入版本、架构、操作系统标签——rkt 在按名发现镜像时会用{os}、{arch}、{version}去替换下载模板中的占位符;
  • annotation add authors:附加镜像元信息;
  • write:写出 ACI 文件;end:结束本次构建会话。

第四步:运行本地 ACI

启动容器

# rkt --insecure-options=image run hello-0.0.1-linux-amd64.aci

这里必须携带--insecure-options=image,因为 rkt 默认要求镜像带有 gpg 签名(见签名与验证指南)。该标志仅针对这一次运行关闭镜像签名校验。它在 全局选项表 中还有http、tls、pubkey、capabilities、paths、seccomp等更细粒度选项,all-fetch/all-run/all则可成组关闭。

此时 hello 应用已经运行并可以响应 HTTP 请求。要停止容器,连续输入三个转义字符(^]^]^],在美式键盘上由Ctrl-]三次产生);也可以把 rkt 交给 init 系统以守护方式运行(详见 run 子命令文档 中 systemd 与 daemon 的用法)。

用 curl 验证服务

默认情况下 rkt 会为容器分配一个 IP 地址,用rkt list查看:

# rkt list UUID APP IMAGE NAME STATE NETWORKS 885876b0 hello example.com/hello:0.0.1 running default:ip4=172.16.28.2

然后直接 curl 该 IP 的 5000 端口:

$ curl 172.16.28.2:5000 hello

可以看到输出正是应用写入的hello,容器网络与进程完全正常。rkt list的列项(UUID 截断、APP、IMAGE NAME、STATE、NETWORKS)由 rkt/list.go 实现:它会遍历数据目录下的全部 pod,读取 pod manifest 与镜像 manifest,并把每个网络接口格式化为网络名:ip4=地址的形式。

第五步:签名——让镜像可以被安全分发

rkt 默认要求 ACI 带 gpg 分离签名。下面完整演示从生成密钥到签发、校验的流程。

生成 gpg 签名密钥

创建名为gpg-batch的批处理文件,内容如下:

%echo Generating a default key Key-Type: RSA Key-Length: 2048 Subkey-Type: RSA Subkey-Length: 2048 Name-Real: Carly Container Name-Comment: ACI signing key Name-Email: carly@example.com Expire-Date: 0 Passphrase: rkt %pubring rkt.pub %secring rkt.sec %commit %echo done

使用批处理模式生成密钥(不指定参数则进入交互模式):

$ gpg --batch --gen-key gpg-batch

列出密钥并建立信任

$ gpg --no-default-keyring \ --secret-keyring ./rkt.sec --keyring ./rkt.pub --list-keys ./rkt.pub ------------ pub 2048R/26EF7A14 2015-01-09 uid [ unknown] Carly Container (ACI signing key) <carly@example.com> sub 2048R/B9C074CD 2015-01-09

此时该密钥的信任等级为unknown,直接校验签名会出现gpg: WARNING: This key is not certified with a trusted signature!的警告。因为我们确切知道密钥来源,可以把它设为最终信任:

$ gpg --no-default-keyring \ --secret-keyring ./rkt.sec \ --keyring ./rkt.pub \ --edit-key 26EF7A14 \ trust

在Your decision?处输入5(trust ultimately)并确认y,随后quit退出。

导出公钥

$ gpg --no-default-keyring --armor \ --secret-keyring ./rkt.sec --keyring ./rkt.pub \ --export carly@example.com > pubkeys.gpg

签名 ACI

对镜像生成分离的 ASCII 装甲签名:

$ gpg --no-default-keyring --armor \ --secret-keyring ./rkt.sec --keyring ./rkt.pub \ --output hello-0.0.1-linux-amd64.aci.asc \ --detach-sig hello-0.0.1-linux-amd64.aci

用 gpg 本地验证

$ gpg --no-default-keyring \ --secret-keyring ./rkt.sec --keyring ./rkt.pub \ --verify hello-0.0.1-linux-amd64.aci.asc hello-0.0.1-linux-amd64.aci gpg: Signature made Fri Jan 9 05:01:49 2015 PST using RSA key ID 26EF7A14 gpg: Good signature from "Carly Container (ACI signing key) <carly@example.com>" [ultimate]

到此你应当拥有三个文件,它们是后续分发与信任演示的基础:

hello-0.0.1-linux-amd64.aci.asc hello-0.0.1-linux-amd64.aci pubkeys.gpg

第六步:通过 Meta Discovery 分发镜像

发布 HTML 与元标签

在example.com/hello页面放置以下 HTML 与 meta 标签:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="ac-discovery" content="example.com/hello https://example.com/images/{name}-{version}-{os}-{arch}.{ext}"> <meta name="ac-discovery-pubkeys" content="example.com/hello https://example.com/pubkeys.gpg"> </head> </html>

并按模板 URL 提供下列文件:

https://example.com/images/example.com/hello-0.0.1-linux-amd64.aci.asc https://example.com/images/example.com/hello-0.0.1-linux-amd64.aci https://example.com/pubkeys.gpg

rkt 的发现流程

执行rkt run example.com/hello:0.0.1时,rkt 会依次请求以下 URI:

https://example.com/hello?ac-discovery=1 https://example.com/images/example.com/hello-0.0.1-linux-amd64.aci https://example.com/images/example.com/hello-0.0.1-linux-amd64.aci.asc

第一次响应里的ac-discovery模板被用于计算 ACI 与签名文件的实际下载地址。其中:

  • {os}与{arch}由当前运行系统的值填充;
  • {version}取命令行给定的 tag,未指定时为latest;
  • {ext}按需替换为.aci(镜像)或.aci.asc(分离签名)。

ACI 下载完成后,rkt 会从镜像元数据中提取镜像名称,据此在 keystore 中定位受信任的公钥并执行签名校验(该发现逻辑在 rkt/image/fetcher.go 中实现,默认会补全arch/os标签后先查本地 store,未命中再走远程发现)。

第七步:建立信任——rkt trust 与 keystore

默认情况下 rkt 不信任任何签名密钥。信任通过把公钥放进 rkt keystore 来建立,可借助rkt trust或手动完成。默认 keystore 布局为:

/etc/rkt/trustedkeys/root.d /etc/rkt/trustedkeys/prefix.d /usr/lib/rkt/trustedkeys/root.d /usr/lib/rkt/trustedkeys/prefix.d

系统管理员应把受信任密钥存放在/etc/rkt下,/usr/lib/rkt预留给操作系统发行版使用。受信任密钥按公钥指纹作为文件名存放。若想"禁用"某个发行版自带的密钥,只需在/etc/rkt下写入同名空文件,例如:

/usr/lib/rkt/trustedkeys/prefix.d/coreos.com/a175e31de7e3c5b9d2c4603e4dfb22bf75ef7a23

对应空文件:

/etc/rkt/trustedkeys/prefix.d/coreos.com/a175e31de7e3c5b9d2c4603e4dfb22bf75ef7a23

方式一:使用 rkt trust(推荐)

对前缀example.com/hello信任从指定 URI 获得的公钥:

$ rkt trust --prefix=example.com/hello https://example.com/pubkeys.gpg Prefix: "example.com/hello" Key: "https://example.com/aci-pubkeys.gpg" GPG key fingerprint is: B346 E31D E7E3 C6F9 D1D4 603F 4DFB 61BF 26EF 7A14 Carly Container (ACI signing key) <carly@example.com> Are you sure you want to trust this key (yes/no)? yes Trusting "https://example.com/aci-pubkeys.gpg" for prefix "example.com/hello". Added key for prefix "example.com/hello" at "/etc/rkt/trustedkeys/prefix.d/example.com/hello/b346e31de7e3c6f9d1d4603f4dfb61bf26ef7a14"

此后指纹为b346e31de7e3c6f9d1d4603f4dfb61bf26ef7a14的公钥将对所有名称前缀为example.com/hello的镜像生效。rkt trust还支持只给前缀不给公钥(走 Meta Discovery 自动寻找),以及用--root信任根域密钥等能力,详见 trust 子命令文档;其实现位于 rkt/trust.go,会校验--prefix与--root互斥、拒绝带 URL scheme 的前缀,并通过--skip-fingerprint-review控制是否需要人工确认指纹。

方式二:手动添加密钥

首先下载公钥并获取其指纹:

$ curl -O https://example.com/pubkeys.gpg
$ gpg --no-default-keyring --with-fingerprint --keyring ./pubkeys.gpg carly@example.com pub 2048R/26EF7A14 2015-01-09 Key fingerprint = B346 E31D E7E3 C6F9 D1D4 603F 4DFB 61BF 26EF 7A14 uid [ unknown] Carly Container (ACI signing key) <carly@example.com> sub 2048R/B9C074CD 2015-01-09

去掉空格并转为小写,得到文件名:

$ echo "B346 E31D E7E3 C6F9 D1D4 603F 4DFB 61BF 26EF 7A14" | \ tr -d "[:space:]" | tr '[:upper:]' '[:lower:]'
b346e31de7e3c6f9d1d4603f4dfb61bf26ef7a14

按指纹命名存放公钥,即可对前缀建立信任:

mkdir -p /etc/rkt/trustedkeys/prefix.d/example.com/hello mv pubkeys.gpg /etc/rkt/trustedkeys/prefix.d/example.com/hello/b346e31de7e3c6f9d1d4603f4dfb61bf26ef7a14

全局信任

若想信任某个公钥用于任意镜像,把它放进root.d目录即可:

/etc/rkt/trustedkeys/root.d /usr/lib/rkt/trustedkeys/root.d

第八步:下载、验证并运行已签名 ACI

通过 run 一步完成

默认情况下 rkt 会自动下载 ACI 的分离签名并校验镜像:

# rkt run example.com/hello:0.0.1 rkt: starting to discover app img example.com/hello:0.0.1 rkt: starting to fetch img from http://example.com/images/example.com/hello-0.0.1-linux-amd64.aci Downloading aci: [ ] 7.24 KB/1.26 MB rkt: example.com/hello:0.0.1 verified signed by: Carly Container (ACI signing key) <carly@example.com> /etc/localtime is not a symlink, not updating container timezone. ^]^]Container stage1 terminated by signal KILL.

输出中的verified signed by表明签名校验成功。若改用--insecure-options=image关闭校验,rkt 会给出醒目警告:

# rkt --insecure-options=image run example.com/hello:0.0.1 rkt: starting to discover app img example.com/hello:0.0.1 rkt: starting to fetch img from http://example.com/images/example.com/hello-0.0.1-linux-amd64.aci rkt: warning: image signature verification has been disabled Downloading aci: [= ] 32.8 KB/1.26 MB /etc/localtime is not a symlink, not updating container timezone. ^]^]Container stage1 terminated by signal KILL.

用 fetch 单独下载验证

rkt fetch可以在不启动 pod 的前提下完成下载与校验,适合在大量主机上预缓存镜像:

# rkt fetch example.com/hello:0.0.1 rkt: starting to discover app img example.com/hello:0.0.1 rkt: starting to fetch img from http://example.com/images/example.com/hello-0.0.1-linux-amd64.aci Downloading aci: [ ] 14.5 KB/1.26 MB rkt: example.com/hello:0.0.1 verified signed by: Carly Container (ACI signing key) <carly@example.com> sha512-b3f138e10482d4b5f334294d69ae5c40

同样可用--insecure-options=image关闭校验(详见 fetch 子命令文档)。最后一行sha512-...是镜像在本地 store 中的 ID,之后可直接用这个 hash 来rkt run sha512-b3f138e10482d4b5f334294d69ae5c40。

第九步:进阶——rkt run 的镜像寻址与运行时覆盖

四种镜像寻址方式

镜像可以按名称、hash、显式传输地址或 Docker Registry URL 来运行,缺失时 rkt 会自动抓取(行为受 镜像抓取策略 控制):

# rkt run coreos.com/etcd:v2.0.0 # rkt run sha512-fa1cb92dc276b0f9bedf87981e61ecde # rkt run https://github.com/coreos/etcd/releases/download/v2.0.0/etcd-v2.0.0-linux-amd64.aci # rkt --insecure-options=image run docker://quay.io/coreos/etcd:v2.0.0

注意 Docker 镜像不支持签名验证,因此使用docker://时通常必须带--insecure-options=image(参见 运行 Docker 镜像文档,rkt 会通过 docker2aci 把分层镜像转换为 ACI)。

同 pod 多应用与参数传递

# rkt run example.com/app1 example.com/app2

向不同应用传参用image1 -- [args] --- image2 -- [args]模式:

# rkt run example.com/worker -- --loglevel verbose --- example.com/syncer -- --interval 30s

结合--exec覆盖启动程序:

# rkt run example.com/worker --exec /bin/ov -- --loglevel verbose --- example.com/syncer --exec /bin/syncer2 -- --interval 30s

常见运行时覆盖

  • --name:覆盖应用名(同名镜像可在同一 pod 中运行多份,如docker://busybox --name=busybox1);
  • --exec:覆盖镜像 manifest 中的exec字段;
  • --cpu=750m --memory=128M:以 Kubernetes 资源模型为单位覆盖 CPU/内存隔离器;
  • --user=1000 --group=100:覆盖运行身份;
  • --inherit-env/--set-env/--set-env-file/--environment:控制环境变量,优先级从父进程环境、镜像环境、文件、命令行到逐应用指定依次递增;
  • --volume NAME,kind=host,source=...,readOnly=...与--mount volume=NAME,target=PATH:挂载卷(host卷与empty卷)到挂载点,未匹配挂载点的卷会被静默忽略,而 manifest 声明的挂载点若无对应卷则自动创建隐式empty卷;
  • --net=host:共享宿主网络栈;不指定时默认--net=default加载默认 contained 网络;
  • --no-overlay=true:显式关闭 overlayfs(默认启用,底层文件系统不支持时会自动降级);
  • --private-users:在用户命名空间内运行。

完整的参数表(含--dns*、--hostname、--hosts-entry、--pod-manifest、--port、--seccomp、--stage1-*等)请参阅 run 子命令文档。

源码视角:run 命令背后的关键路径

  • 参数解析与校验集中在 rkt/run.go:runRun先解析 app 参数,检查--port与--net、--mds-register与--net的冲突,随后依次打开 imagestore、treestore,解析配置、解析 stage1 镜像 hash,再通过image.Finder按--pull-policy抓取镜像,最终构造stage0.RunConfig交给stage0.Run(该调用是 exec 语义,不会返回)。
  • 镜像抓取逻辑见 rkt/image/fetcher.go:FetchImage按镜像参数类型分发——本地 ACI 归档走file/http(s),Docker 走dockerFetcher,名称类走 Meta Discovery(nameFetcher),并可通过--pull-policy的never/new/update控制是否联网(默认run/prepare为new,fetch为update,见 镜像抓取行为文档)。
  • 若要从私有仓库抓取镜像,可在/etc/rkt/auth.d下按 configuration.md 的auth/dockerAuthkind 配置 basic、OAuth、AWS v4 或 Docker Registry 凭据,系统目录(/usr/lib/rkt)、本地目录(/etc/rkt)与用户目录(--user-config)支持逐字段覆盖。

结语:完整发布链路回顾

至此你已经走通了从源码到可安全分发的完整链路:静态编译 Go 应用 →acbuild打包 ACI → 本地rkt run+curl验证 → gpg 签名 → 在域名下配置ac-discoverymeta 标签 →rkt trust建立信任 →rkt run example.com/hello:0.0.1由 Meta Discovery 自动定位、下载并验证镜像后运行。这一流程正是 rkt 作为 App Container 规范参考实现的核心使用范式,也体现了它"可组合、安全、基于标准"的设计理念。

  • 容器运行时
  • 云原生
  • 网络

【免费下载链接】rkt

[Project ended] rkt is a pod-native container engine for Linux. It is composable, secure, and built on standards.

项目地址:https://gitcode.com/gh_mirrors/rk/rkt
点击查看免费下载

相关推荐

上一篇:ncmdump:2 个动作把 NCM 变成 MP3(免费、离线)
下一篇:一条命令解开PKG:RePKG的TEX转PNG纹理提取

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询