跳转至

Containerd 删除 标签镜像指南

问题描述

在使用 containerd 作为容器运行时过程中,经常会遇到镜像标签显示为 <none> 的情况。这些镜像通常是由于以下原因产生的:

  1. 构建新镜像时覆盖了旧镜像的标签
  2. 使用 docker pullctr image pull 时没有指定标签
  3. 镜像被重新标记后,原标签变为 <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. 注意事项

  • 使用 saveload 命令可以完整保存镜像的所有层
  • 使用 exportimport 命令会丢失镜像的历史和元数据
  • 建议使用有意义的标签来标记镜像,避免出现 <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

注意事项

  1. 谨慎操作
  2. 删除镜像前确认镜像 ID
  3. 确保没有容器正在使用该镜像

  4. 检查依赖关系

    # 检查是否有容器使用该镜像
    ctr -n k8s.io containers ls | grep <image-id>
    

  5. 备份重要镜像

  6. 删除前建议备份重要镜像
  7. 可以使用 ctr images export 导出镜像

最佳实践

  1. 定期清理
  2. 建议定期检查并清理 <none> 标签镜像
  3. 可以设置定时任务自动清理

  4. 使用脚本自动化

    #!/bin/bash
    # 清理 <none> 标签镜像脚本
    ctr -n k8s.io images ls | grep "<none>" | awk '{print $3}' | xargs -I {} ctr -n k8s.io images rm {}
    

  5. 监控磁盘空间

  6. 定期检查 containerd 存储空间使用情况
  7. 及时清理无用镜像

故障排除

  1. 删除失败
  2. 检查是否有容器正在运行
  3. 确认镜像 ID 是否正确
  4. 检查权限问题

  5. 空间未释放

  6. 使用 ctr content ls 检查内容存储
  7. 可能需要手动清理未引用的内容

参考文档

回到页面顶部