为什么使用 img 构建容器镜像比传统 Docker 更轻量高效

来源:Redis教程作者:会飞的猪头衔:草根站长
导读:本期聚焦于小伙伴创作的《为什么使用 img 构建容器镜像比传统 Docker 更轻量高效》,敬请观看详情。把构建容器镜像的过程从守护进程里剥离出来,是近年来不少团队优化 CI 效率的关键一步。img 这款工具基于 BuildKit 库实现,直接在用户态完成镜像的拉取、构建与推送,不需要本机运行 Docker 守护进程。它利用 Linux 的 user namespace 模拟 root 权限,普通账号也能制作包含 apt 安装、用户切换等操作的镜像。相比传统 Docker 构建,img 在资源占用、权限安全和流水线适配上有明显差异,尤其在无特权容器环境里几乎成为唯一选择。理解它的运行原理和实操命令,能帮助你在受限服务器上稳定产出符合 OCI 标准的镜像。

在容器技术日常落地的过程中,镜像构建方式直接影响交付速度和运行安全。传统 Docker 构建依赖长期运行的 dockerd 守护进程,这种模式在共享主机或 CI Runner 中容易遇到权限冲突和资源争抢。img 是一个用 Go 编写的命令行工具,它把 BuildKit 的核心能力封装成无守护进程的构建器,让用户在没有任何容器守护程序的环境下也能产出标准镜像。

为什么使用 img 构建容器镜像比传统 Docker 更轻量高效

img 的底层构建原理与命名空间隔离

img 并不自己实现镜像层打包逻辑,而是引用了 moby/buildkit 前端库,将构建指令翻译成 LLB(Low-Level Build)中间语言,再由内置的 executor 在本地执行。最关键的一点是,img 使用 Linux 的 user namespace 把容器内的 uid 0 映射到宿主机的普通用户,从而在不申请真正 root 权限的情况下完成需要写系统目录、改用户态配置的步骤。这种方式绕开了 dockerd 必须监听 Unix socket 且常以 root 运行的束缚。

在 user namespace 之上,img 还借助 overlayfs 或 native snapshotter 管理分层文件系统。每一条 Dockerfile 指令产生的变更都会被记录为只读层,最终依据 OCI image-spec 合成 manifest 与 config。因为构建进程本身就是调用方用户,所以生成的镜像在权限归属上更清晰,不会出现 root 创建的层导致后续非 root 环境无法清理的问题。下面是一段在 Ubuntu 普通账号下使用 img 构建简单镜像的示例:

# 安装 img 二进制
curl -fL https://github.com/genuinetools/img/releases/download/v0.5.11/img-linux-amd64 -o /usr/local/bin/img
chmod +x /usr/local/bin/img

# 编写最小 Dockerfile
cat > Dockerfile <<'EOF'
FROM alpine:3.18
RUN adduser -D appuser
USER appuser
CMD ["sh"]
EOF

# 使用 img 构建并打标签
img build -t ipipp.com/demo/mini:latest .

上述命令中,即使在禁止 docker 命令的服务器上,只要内核开启 user namespace,就能顺利执行。对比 docker build 需要事先启动服务,img 的冷启动几乎只受二进制加载速度影响。对于临时 Runner 来说,省去守护进程初始化就意味着更短的排队和更低的失败率。

与传统 Docker 构建在权限和 CI 场景的对比

传统 Docker 构建要求执行者拥有访问 docker.sock 的权限,这在多租户 CI 平台中往往等于变相授予宿主机 root。img 把权限边界收缩到单个用户命名空间,配合 --state 与 --cache 参数还能把构建缓存放在用户目录,避免不同项目互相污染。下表列出了两者在几个关键维度的差异:

维度Docker 构建img 构建
守护进程必须运行 dockerd无需任何守护进程
权限模型常需 root 或 docker 组普通用户加 user namespace
缓存位置由 dockerd 统一管理可指定用户态目录
适用环境开发机、特权节点无特权容器、CI Runner

在 GitHub Actions 的自托管 Runner 中,如果 Runner 本身以容器方式部署且没有特权模式,docker build 会直接报错。此时将 img 作为构建步骤的替代,不仅能通过,还能利用层缓存加速。需要注意的是,img 目前对多平台交叉构建的支持不如最新 Buildx 完善,若需同时出 amd64 与 arm64 镜像,应评估是否配合 QEMU 用户态模拟。

另一个常被忽略的点是镜像推送。img 内置了 registry 客户端,支持直接把产物推送到支持 OCI 的仓库。由于推送动作也运行在用户态,不会在宿主机留下匿名 volume,对磁盘运维更友好。以下示例展示如何免 sudo 推送到远程:

# 登录镜像仓库,凭证存入 ~/.config/img
img login ipipp.com -u builder -p secretpass

# 构建并推送
img build -t ipipp.com/demo/mini:latest -push .

从这段流程可以看出,整个构建加推送没有调用任何系统级服务,所有网络与文件操作都可被用户配额限制,非常适合在受限沙箱中做合规审计。

实操中的常见误区与分层优化建议

不少初次接触 img 的开发者会误以为它只是 docker 命令的别名,于是沿用 Docker 守护进程的思维,比如试图用 docker images 查看 img 产物。实际上 img 的本地索引存放在用户目录的 state 文件夹,必须通过 img lsimg inspect 查看。若强行混合使用,容易造成层数统计混乱。理解这一点是排错的第一步。

在编写 Dockerfile 时,为了充分发挥 img 的层缓存优势,应当把变动频率低的指令放在前面。由于 img 的 snapshotter 对 RUN 指令的内容哈希敏感,哪怕只是调整了注释顺序也可能让缓存失效。建议把依赖安装与源码拷贝分开,并利用 --build-arg 传递环境差异。示例展示带缓存优化的写法:

FROM node:18-alpine
WORKDIR /app
# 先拷贝依赖描述,利用缓存
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
# 再拷贝源码,源码变动不影响依赖层
COPY src ./src
CMD ["node", "src/index.js"]

此外,img 对 .dockerignore 的支持与 Docker 基本一致,但部分旧版本在嵌套目录过滤上略有偏差。建议在 CI 脚本里显式打印构建上下文大小,确认无关文件未被打入。当镜像最终需要交给 Kubernetes 拉取时,只要仓库支持 OCI 分发,img 产出的镜像无需任何转换即可被 containerd 或 cri-o 直接识别,这也是它在云原生流水线里逐渐被采纳的根本原因。

imgbuild_container_imageOCI_image修改时间:2026-08-16 09:40:30

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。