Containerd 删除 标签镜像指南 ¶
问题描述¶
在使用 containerd 作为容器运行时过程中,经常会遇到镜像标签显示为 <none>
的情况。这些镜像通常是由于以下原因产生的:
- 构建新镜像时覆盖了旧镜像的标签
- 使用
docker pull
或ctr image pull
时没有指定标签 - 镜像被重新标记后,原标签变为
<none>
使用 nerdctl 作为 Docker 替代品¶
1. 设置别名¶
# 将 nerdctl 设置为 Docker 替代品
alias docker='nerdctl --namespace k8s.io'
2. 使用 Docker 命令格式¶
使用上述别名后,可以直接使用熟悉的 Docker 命令格式:
# 查看所有镜像
docker images
# 查看 <none> 标签镜像
docker images | grep "<none>"
# 删除单个镜像(使用完整镜像ID)
docker rmi 5c209cd32ee4
# 批量删除所有 <none> 标签镜像(方法1)
docker images | grep "<none>" | awk '{print $3}' | xargs -I {} nerdctl --namespace k8s.io rmi {}
# 批量删除所有 <none> 标签镜像(方法2)
nerdctl --namespace k8s.io images | grep "<none>" | awk '{print $3}' | xargs -I {} nerdctl --namespace k8s.io rmi {}
# 批量删除所有 <none> 标签镜像(方法3 - 更安全的方式)
docker images | grep "<none>" | while read -r _ _ id _; do nerdctl --namespace k8s.io rmi "$id"; done
3. 注意事项¶
- 所有命令会自动使用
k8s.io
命名空间 - 命令行为与 Docker 保持一致
- 适用于 Kubernetes 容器运行时环境
- 在脚本或 xargs 中使用时,建议直接使用
nerdctl --namespace k8s.io
而不是docker
别名 - 删除镜像时建议使用完整的镜像 ID,避免使用前缀导致误删
- 如果遇到 "multiple IDs found" 错误,请使用完整的镜像 ID 进行删除
使用 ctr 命令删除镜像(当 nerdctl 失败时)¶
当使用 nerdctl
删除镜像遇到 "multiple IDs found" 错误时,可以使用 ctr
命令作为替代方案:
# 查看镜像详细信息
ctr -n k8s.io images ls | grep 5c209cd32ee4
# 使用 ctr 删除镜像
ctr -n k8s.io images rm 5c209cd32ee4
# 批量删除所有 <none> 标签镜像
ctr -n k8s.io images ls | grep "<none>" | awk '{print $1}' | xargs -I {} ctr -n k8s.io images rm {}
注意事项¶
ctr
命令是 containerd 的原生命令,通常能更可靠地处理镜像删除- 使用
ctr
时,镜像 ID 需要包含完整的仓库路径 - 如果仍然遇到问题,可以尝试先使用
ctr images ls
查看完整的镜像信息
使用 nerdctl 保存和标记镜像¶
1. 保存镜像¶
# 将镜像保存为 tar 文件
nerdctl --namespace k8s.io save -o image.tar <image-id>
# 从 tar 文件加载镜像
nerdctl --namespace k8s.io load -i image.tar
2. 标记镜像¶
# 为镜像添加标签
nerdctl --namespace k8s.io tag <image-id> <repository>:<tag>
# 示例:将 <none> 标签镜像标记为有意义的标签
nerdctl --namespace k8s.io tag 5c209cd32ee4 myapp:latest
3. 导出和导入镜像¶
# 导出镜像
nerdctl --namespace k8s.io export -o container.tar <container-id>
# 导入镜像
nerdctl --namespace k8s.io import container.tar <repository>:<tag>
4. 注意事项¶
- 使用
save
和load
命令可以完整保存镜像的所有层 - 使用
export
和import
命令会丢失镜像的历史和元数据 - 建议使用有意义的标签来标记镜像,避免出现
<none>
标签 - 在标记镜像时,确保使用唯一的标签名
查看 标签镜像 ¶
1. 使用 ctr 命令¶
# 查看所有镜像
ctr -n k8s.io images ls
# 查看 <none> 标签镜像
ctr -n k8s.io images ls | grep "<none>"
2. 使用 nerdctl 命令¶
# 查看所有镜像
nerdctl images
# 查看 <none> 标签镜像
nerdctl images | grep "<none>"
删除 标签镜像 ¶
1. 使用 ctr 命令删除¶
# 删除单个镜像
ctr -n k8s.io images rm <image-id>
# 批量删除所有 <none> 标签镜像
ctr -n k8s.io images ls | grep "<none>" | awk '{print $3}' | xargs -I {} ctr -n k8s.io images rm {}
2. 使用 nerdctl 命令删除¶
# 删除单个镜像
nerdctl rmi <image-id>
# 批量删除所有 <none> 标签镜像
nerdctl images | grep "<none>" | awk '{print $3}' | xargs -I {} nerdctl rmi {}
镜像打包¶
指定 k8s.io 命名空间,可以使用以下命令打包该命名空间下所有非 nerdctl -n k8s.io image list --format "{{.Repository}}:{{.Tag}}" | grep -v "<none>$" | xargs -r nerdctl -n k8s.io save -o k8s-images.tar
镜像名称格式
某些镜像的 Repository 字段可能为空(如 k8s.gcr.io/pause:3.6 这类基础镜像),若 --format 输出结果为 :
nerdctl -n k8s.io image list --format "{{.Repository}}:{{.Tag}}"
旧版本兼容性 若 nerdctl 版本不支持 --format,改用以下命令手动过滤:
nerdctl -n k8s.io image list | awk 'NR>1 && !/<none>/ {print $1":"$2}' | xargs -r nerdctl -n k8s.io save -o k8s-images.tar
附:清理
如果希望直接清理无效镜像(谨慎操作):
nerdctl -n k8s.io image prune -f
注意事项¶
- 谨慎操作
- 删除镜像前确认镜像 ID
-
确保没有容器正在使用该镜像
-
检查依赖关系
# 检查是否有容器使用该镜像 ctr -n k8s.io containers ls | grep <image-id>
-
备份重要镜像
- 删除前建议备份重要镜像
- 可以使用
ctr images export
导出镜像
最佳实践¶
- 定期清理
- 建议定期检查并清理
<none>
标签镜像 -
可以设置定时任务自动清理
-
使用脚本自动化
#!/bin/bash # 清理 <none> 标签镜像脚本 ctr -n k8s.io images ls | grep "<none>" | awk '{print $3}' | xargs -I {} ctr -n k8s.io images rm {}
-
监控磁盘空间
- 定期检查 containerd 存储空间使用情况
- 及时清理无用镜像
故障排除¶
- 删除失败
- 检查是否有容器正在运行
- 确认镜像 ID 是否正确
-
检查权限问题
-
空间未释放
- 使用
ctr content ls
检查内容存储 - 可能需要手动清理未引用的内容