前言
以前玩 Docker 基本都是捣鼓别人制作好的镜像,自己 build 好的镜像一般也不会去 Push 到 Hub 上丢人。随着 CNB 的崛起,这两天也开始尝试去推送到 CNB 的制品库来快速启动。但是动辄几十上百 G 的镜像,docker push 实在是耗时。被 @Anthony 指点后,遂知道了原因。
原因剖析
1. 同步压缩与推送的机制限制
边压缩边推送:Docker Push 在推送镜像时需实时压缩每一层数据(Layer),压缩与网络传输同步进行,导致两者形成串行流水线。
对比优化方案:其他工具(如
skopeo
、curl
)采用先压缩后推送策略,分离压缩与传输步骤,可充分利用带宽。
2. 单线程压缩算法瓶颈
低效的压缩实现:Docker 默认使用单线程
gzip -6
压缩算法,无法利用多核 CPU 资源。理论对比:
pigz
(多线程替代品)可将压缩速度提升数倍(如 4 核下接近线性加速)。社区进展:Moby 社区已提出 PR #44008 改用
pigz
,但尚未合入主线。
3. 压缩耗时与传输耗时叠加
时间成本翻倍:压缩耗时与网络传输耗时直接叠加(而非并行)。
示例计算:280MB 镜像单线程压缩耗时约 9.5秒,传输耗时 9.5秒,总耗时 19秒(未含元数据操作)。
对比理想场景:若采用预压缩或多线程压缩,总时间可接近纯传输耗时(9.5秒 + 少量开销)。
4. 临时解决方案与替代工具
绕过 Docker 限制:
skopeo
:支持直接推送预压缩的镜像,避免实时压缩开销。curl
+ OCI 规范:通过 OCI 一致性测试工具 手动推送,完全控制压缩与传输流程。
安全性取舍:
docker buildx build --push
虽快,但因安全限制无法开放给用户。
解决方案
通过对比,采用 skopeo 进行镜像的推送,能够大幅提升网络占用率,缩短镜像推送时间。
1. 安装
编译安装实在慢,来试试这个:
wget -O /usr/bin/skopeo https://github.com/lework/skopeo-binary/releases/latest/download/skopeo-linux-amd64 && chmod +x /usr/bin/skopeo
2. 使用
root@ubuntu:~# skopeo --help
Various operations with container images and container image registries
Usage:
skopeo [flags]
skopeo [command]
Available Commands:
copy Copy an IMAGE-NAME from one location to another
delete Delete image IMAGE-NAME
generate-sigstore-key Generate a sigstore public/private key pair
help Help about any command
inspect Inspect image IMAGE-NAME
list-tags List tags in the transport/repository specified by the SOURCE-IMAGE
login Login to a container registry
logout Logout of a container registry
manifest-digest Compute a manifest digest of a file
standalone-sign Create a signature using local files
standalone-verify Verify a signature using local files
sync Synchronize one or more images from one location to another
Flags:
--command-timeout duration timeout for the command execution
--debug enable debug output
-h, --help help for skopeo
--insecure-policy run the tool without any policy check
--override-arch ARCH use ARCH instead of the architecture of the machine for choosing images
--override-os OS use OS instead of the running OS for choosing images
--override-variant VARIANT use VARIANT instead of the running architecture variant for choosing images
--policy string Path to a trust policy file
--registries.d DIR use registry configuration files in DIR (e.g. for container signature storage)
--tmpdir string directory used to store temporary files
-v, --version Version for Skopeo
Use "skopeo [command] --help" for more information about a command.
Repository Type | Description | Example |
---|---|---|
containers-storage:docker-reference |
适用于后端是 Podman, CRI-O, Buildah 的情况 | containers-storage: |
dir:path |
适用于将 manifest, layer tarballs 和 signatures 存储为单独文件的本地目录路径 | dir:/tmp/alpine:latest |
docker://docker-reference |
适用于 Registry 中实现 “Docker Registry HTTP API V2” 的镜像 | docker://harbor.weiyigeek.top/myblog:v2.8 |
docker-archive:path[:docker-reference] |
适用于采用 docker save 命令导出镜像以 tar 格式存储的文件 |
docker-archive:alpine.tar |
docker-daemon:docker-reference |
适用于存储在 Docker 守护进程内部存储中的图像 | docker-daemon:alpine:latest |
oci:path:tag |
适用于符合 “Open Container Image Layout Specification” 的目录中的图像标记 | oci:alpine:latest |
3. 示例
构建推送
docker build -t docker.cnb.cool/anyexyz/qwq/32b:fp16 .
skopeo login docker.cnb.cool
skopeo copy --insecure-policy docker-daemon:docker.cnb.cool/anyexyz/qwq/32b:fp16 docker://docker.cnb.cool/anyexyz/qwq/32b:fp16
速度展示