1. 简介

Docker 镜像在容器化应用中扮演着核心角色。但在某些情况下,由于镜像构建历史的复杂性,我们可能难以准确识别某个镜像所使用的基镜像(Base Image)。

本文将介绍几种常见的方法来查看 Docker 镜像的基镜像,包括使用 Docker Scout、dive 工具以及原生的 Docker 命令,并分析每种方法的优缺点和适用场景。


2. 使用 Docker Scout 查看基镜像

Docker Scout 是一种快速、可靠地识别基镜像的方式

如果你使用的是 Docker Engine,可能需要手动安装 Docker Scout。但如果你使用的是 Docker Desktop,则 Docker Scout 已经预装好了。

我们以 postgres:17.2 镜像为例,使用如下命令查看其基镜像:

$ docker scout quickview postgres:17.2
...
...
  Target             │  postgres:17.2       │    3C    35H    16M    36L     1?
    digest           │  80cbdc6c3301        │                                  
  Base image         │  debian:12-slim      │    0C     0H     0M    23L
                     │                      

输出显示,postgres:17.2 的基镜像是 debian:12-slim

但 Docker Scout 也有局限性:它依赖于 Docker Hub 的元数据,因此对于本地构建、未上传到 Docker Hub 的镜像,它可能无法正确识别其基镜像。


3. 手动查找基镜像

当 Docker Scout 无法识别基镜像时,我们可以尝试通过分析镜像的构建历史来手动识别。

⚠️ 手动识别容易出错,因为 Docker 镜像是由多个只存储增量变化的层(Layer)组成,而这些层中并不包含关于基镜像的元信息。

识别流程大致如下:

  1. 使用 docker history 查看镜像构建历史
  2. 利用 dive 工具获取特定层的 digest
  3. 将 digest 与本地已有镜像的 digest 进行匹配

3.1. 使用 docker history 查看构建历史

我们以 postgres:17.2 为例:

$ docker history postgres:17.2
IMAGE          CREATED       CREATED BY                                      SIZE      COMMENT
80cbdc6c3301   8 days ago    CMD ["postgres"]                                0B        buildkit.dockerfile.v0
<missing>      8 days ago    EXPOSE map[5432/tcp:{}]                         0B        buildkit.dockerfile.v0
<missing>      8 days ago    STOPSIGNAL SIGINT                               0B        buildkit.dockerfile.v0
...
...
...
<missing>      8 days ago    RUN /bin/sh -c set -eux;  groupadd -r postgr…   4.32kB    buildkit.dockerfile.v0
<missing>      2 weeks ago   CMD ["bash"]                                    0B        buildkit.dockerfile.v0
<missing>      2 weeks ago   ADD rootfs.tar.xz / # buildkit                  74.8MB    buildkit.dockerfile.v0

通常,基镜像的构建会在某个 CMDENTRYPOINT 指令之前结束。因此,我们可以关注 ADD rootfs.tar.xz 这一层,作为潜在的基镜像层。

3.2. 使用 dive 获取层的 digest

我们先为 dive 创建一个别名:

$ alias dive='docker run -ti --rm -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive'

然后运行:

$ dive postgres:17.2
┃ ● Layers ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 
Cmp   Size  Command                                                      
     75 MB  FROM blobs                                                   
    4.3 kB  RUN /bin/sh -c set -eux;     groupadd -r postgres --gid=999; 
                                                                         
│ Layer Details ├─────────────────────────────────────────────────────── 
                                                                         
Tags:   (unavailable)                                                    
Id:     blobs                                                            
Digest: sha256:c3548211b8264f8bfa47a6727043a64f1791b82ac965a284a7ea187e9 

我们得到了该层的 digest:sha256:c3548211b8264f8bfa47a6727043a64f1791b82ac965a284a7ea187e9

3.3. 匹配 digest

接下来我们遍历本地所有镜像,查找包含该 digest 的镜像:

$ for image in $(docker images -q)
do
    if [[ $(docker inspect $image | grep "sha256:c3548211b8264f8bfa47a6727043a64f1791b82ac965a284a7ea187e971a95e2") ]]
    then
        docker images | grep $image
    fi
done

输出结果中包含两个镜像:

postgres                17.2                80cbdc6c3301   8 days ago      435MB
debian                  12-slim             762d928e7cfb   2 weeks ago     74.8MB

我们再检查 debian:12-slim 的 RootFS 层:

$ docker inspect debian:12-slim | jq '.[].RootFS'
{
  "Type": "layers",
  "Layers": [
    "sha256:c3548211b8264f8bfa47a6727043a64f1791b82ac965a284a7ea187e971a95e2"
  ]
}

确认 debian:12-slimpostgres:17.2 的基镜像

⚠️ 该方法的局限性在于:如果本地没有该基镜像,就无法匹配成功;如果多个镜像共享相同的层,也可能导致误判。


4. 小结

本文介绍了三种确定 Docker 镜像基镜像的方法:

方法 优点 缺点
Docker Scout 快速、准确 仅适用于 Docker Hub 上的镜像
dive + docker history + digest 匹配 适用于本地镜像 操作复杂、易出错、依赖本地镜像存在
原生命令组合 无需额外工具 精度低、过程繁琐

推荐优先使用 Docker Scout,除非你需要分析本地构建的私有镜像。

⚠️ 手动识别方式应作为最后的备选手段,因为它依赖于本地镜像存在,且容易误判。

如果你在 CI/CD 或镜像构建过程中需要自动化识别基镜像,建议在构建时显式记录基镜像信息,避免后续查找的麻烦。


原始标题:Finding the Base Image of a Docker Image