docker image tag为什么出现none

今天和小伙伴们,聊一个工作中遇到的小问题~

背景

公司项目是基于容器化架构设计,具体业务也拆成了多个微服务及对应了多个docker image镜像。研发环境中会频繁进行升级image镜像,导致出现很多image为 <none> 命名的镜像,这种也称为悬空镜像。

本篇文章将展示几种现象会导致这种情况发生。

下文演示环境,版本信息如下

  • Centos8
  • docker server: 23.0.1
  • docker client: 20.10.17
  • containerd: 1.6.18
  • runc version: 1.1.4

现象一

前提条件: 在同环境中两个镜像名称:tag都相同,image层数据内容不一致,覆盖后则会出现 <none> 标志。

注意: 如果仅是镜像名称:tag相同则不会覆盖,也不会出现 <none> 标志。 因为image层数据没有发生变化,docker认为是同一个镜像。

shell 复制代码
[root@k8s-host docker]# cat > Dockerfile << EOF
> FROM alpine:latest
> ADD test.txt /root
> EOF
[root@k8s-host docker]# echo 1 > test.txt
[root@k8s-host docker]# docker build -t alpine1:v1.0 .
[+] Building 0.1s (7/7) FINISHED                                                                                                                                    
 => [internal] load build definition from Dockerfile                                                                                                           0.0s
 => => transferring dockerfile: 134B                                                                                                                           0.0s
 => [internal] load .dockerignore                                                                                                                              0.0s
 => => transferring context: 2B                                                                                                                                0.0s
 => [internal] load metadata for docker.io/library/alpine:latest                                                                                               0.0s
 => [internal] load build context                                                                                                                              0.0s
 => => transferring context: 96B                                                                                                                               0.0s
 => CACHED [1/2] FROM docker.io/library/alpine:latest                                                                                                          0.0s
 => [2/2] ADD test.txt /root                                                                                                                                   0.0s
 => exporting to image                                                                                                                                         0.0s
 => => exporting layers                                                                                                                                        0.0s
 => => writing image sha256:aa416b5c47216b392755ba2b4ad08f5531f3aa86c103744e261e49ce7a354021                                                                   0.0s
 => => naming to docker.io/library/alpine1:v1.0                                                                                                                0.0s
 [root@k8s-host docker]# docker images
REPOSITORY                                TAG       IMAGE ID       CREATED          SIZE
alpine1                                   v1.0      aa416b5c4721   30 seconds ago   7.34MB

该镜像是基于alpine:latest镜像进行二次编译

Dockerfile中仅增加 test.txt 用来区分层内容

Dockerfile 复制代码
FROM alpine:latest
ADD test.txt /root

上述步骤中执行 docker images 可以看到 alpine1:v1.0 已经存在镜像ID aa416b5c4721 的容器镜像。

下面继续编译镜像,名字与 alpine1:v1.0 相同, 仅仅将Dockerfile中 test.txt 文件内容修改。

进行第二次加载镜像,此时系统已存在相同的镜像名称。

shell 复制代码
[root@k8s-host docker]# echo 2 > test.txt 
[root@k8s-host docker]# docker build -t alpine1:v1.0 .
[+] Building 0.1s (7/7) FINISHED                                                                                                                                    
 => [internal] load build definition from Dockerfile                                                                                                           0.0s
 => => transferring dockerfile: 134B                                                                                                                           0.0s
 => [internal] load .dockerignore                                                                                                                              0.0s
 => => transferring context: 2B                                                                                                                                0.0s
 => [internal] load metadata for docker.io/library/alpine:latest                                                                                               0.0s
 => [internal] load build context                                                                                                                              0.0s
 => => transferring context: 96B                                                                                                                               0.0s
 => CACHED [1/2] FROM docker.io/library/alpine:latest                                                                                                          0.0s
 => [2/2] ADD test.txt /root                                                                                                                                   0.0s
 => exporting to image                                                                                                                                         0.0s
 => => exporting layers                                                                                                                                        0.0s
 => => writing image sha256:e4159797272a190d20856475858bab23d11e64d6bdd9a57ca8a85ad3c3a17087                                                                   0.0s
 => => naming to docker.io/library/alpine1:v1.0                                                                                                                0.0s
[root@k8s-host docker]# docker images
REPOSITORY                                TAG       IMAGE ID       CREATED          SIZE
alpine1                                   v1.0      e4159797272a   3 seconds ago    7.34MB
<none>                                    <none>    aa416b5c4721   6 minutes ago    7.34MB

原来的 alpine1:v1.0 镜像ID为 aa416b5c4721 的docker镜像目前属于 none 标记,这是因为有了新的镜像名称相同造成。虽然是none标记,如果之前有引用的容器仍然可以使用。

注意:如果将 alpine1:v1.0 镜像ID为 e4159797272a 的docker镜像删除, 下面的none标记也不会发生变化。只有当时的 Dockerfile中的 ADD 文件重新docker build -t alpine1:v1.0编译,此处的 none 标记才能显示正常。

现象二

docker save 时镜像没有指定镜像名称:tag,而是使用的镜像ID。

shell 复制代码
[root@k8s-host docker]# docker images
REPOSITORY                                TAG       IMAGE ID       CREATED          SIZE
alpine1                                   v1.0      e4159797272a   3 seconds ago    7.34MB
[root@k8s-host docker]# docker save e4159797272a | gzip > alpine1.docker
[root@k8s-host docker]# docker rmi e4159797272a
Untagged: alpine1:v1.0
Deleted: sha256:e4159797272a190d20856475858bab23d11e64d6bdd9a57ca8a85ad3c3a17087
[root@k8s-host docker]# docker load < alpine1.docker 
Loaded image ID: sha256:e4159797272a190d20856475858bab23d11e64d6bdd9a57ca8a85ad3c3a17087
[root@k8s-host docker]# docker images
REPOSITORY                                TAG       IMAGE ID       CREATED          SIZE
<none>                                    <none>    e4159797272a   21 minutes ago   7.34MB

操作中,将alpine1:v1.0镜像没有按照镜像:tag方式 save,而是使用 docker save e4159797272a 镜像ID格式保存, 仅仅微小的变化会导致镜像加载时的效果不同。

当执行完 docker load < alpine1.docker 加载镜像后发现,此时的镜像ID还是原来没有变化,而镜像名称:TAG 都变成none。

注意:如果 docker save 导出镜像时不指定 镜像名称:tag 这种方式,在docker load 加载镜像时会丢失镜像名称和tag标记。

现象三

正运行的容器所引用的镜像,将其强行删除镜像docker images会出现none标记

shell 复制代码
[root@k8s-host docker]# docker images
REPOSITORY                                TAG       IMAGE ID       CREATED         SIZE
alpine4                                   v1.0      7ea0f12a3321   7 hours ago     7.34MB
[root@k8s-host docker]# docker rmi alpine4:v1.0
Error response from daemon: conflict: unable to remove repository reference "alpine4:v1.0" (must force) - container 945e9f47d833 is using its referenced image 7ea0f12a3321
[root@k8s-host docker]# docker rmi -f alpine4:v1.0
Untagged: alpine4:v1.0
[root@k8s-host docker]# docker ps -a | grep alpine
945e9f47d833   7ea0f12a3321   "/bin/sh -c 'tail -f..."   54 seconds ago   Up 53 seconds             alpine4
[root@k8s-host docker]# docker images
REPOSITORY                                TAG       IMAGE ID       CREATED         SIZE
<none>                                    <none>    7ea0f12a3321   7 hours ago     7.34MB

操作中执行 docker rmi -f alpine4:v1.0 命令后,仅删除了镜像:tag,并没有删除镜像数据层。

可以看到只有镜像名称:tag 变成了none,实际的镜像还是存在的。因为目前 945e9f47d833 容器中引用到了 7ea0f12a3321 镜像是无法使用 docker rmi -f 删除的。

扩展内容

尤其在测试、研发环境中会出现很多 <none> 标记的镜像,占用较多资源。 在docker cli工具中可以使用如下命令来清理未使用的镜像。

shell 复制代码
$ docker system prune

注意:该命令包含删除所有未使用的容器、网络、镜像(悬空的和未引用的),以及卷(可选)。

也可单独删除所有无名的镜像(悬空镜像)

shell 复制代码
$ docker rmi $(docker images -f "dangling=true" -q)

技术文章持续更新,请大家多多关注呀~~

搜索微信公众号,关注我【 帽儿山的枪手 】

相关推荐
意倾城13 分钟前
Docker常见命令解读
docker·容器
源码方舟1 小时前
SpringBoot + Shiro + JWT 实现认证与授权完整方案实现
java·spring boot·后端
热河暖男5 小时前
【实战解决方案】Spring Boot+Redisson构建高并发Excel导出服务,彻底解决系统阻塞难题
spring boot·后端·excel
我没有开挂6 小时前
旧 docker 版本通过 nvkind 搭建虚拟多节点 gpu 集群的坑
运维·docker·容器
小鸡,啄米6 小时前
centos9安装docker 配置docker代理
运维·docker·容器
遇见火星8 小时前
jenkins流水线常规配置教程!
运维·docker·jenkins
LunarCod9 小时前
Ubuntu使用Docker搭建SonarQube企业版(含破解方法)
linux·运维·服务器·ubuntu·docker·开源·sonarqube
noravinsc9 小时前
redis是内存级缓存吗
后端·python·django
noravinsc10 小时前
django中用 InforSuite RDS 替代memcache
后端·python·django
喝醉的小喵10 小时前
【mysql】并发 Insert 的死锁问题 第二弹
数据库·后端·mysql·死锁