Docker:通过摘要提取图像,该图像内部使用标签

时间:2019-03-28 22:49:07

标签: docker dockerfile digest

以dockerhub上托管的以下存储库为例: https://hub.docker.com/r/frolvlad/alpine-miniconda3


执行以下命令以通过摘要提取图像:

docker pull frolvlad/alpine-miniconda3:python3.7@sha256:9bc9c096713a6e47ca1b4a0d354ea3f2a1f67669c9a2456352d28481a6ce2fbe


基于docker documentation,通过摘要提取图像具有以下属性:

  

使用此功能可将图像及时“固定”到特定版本

据我了解,在任何时候用该摘要提取的docker镜像都是不可变的。
尽管它没有评论可变的或内部似乎可变的引用。

最重要的是,first line of the docker file读为

FROM frolvlad/alpine-glibc:alpine-3.9

如果作者更改了dockerfile中的第一行并推送(即使它是同一标签),我将根据我的阅读来假设,即使我指向图像摘要,也不会受到影响。然而, 由于作者引用了dockerfile中的标签而不是摘要,因此我如何确认使用了哪个dockerfile / base映像来构建其映像?似乎仅分析frolvlad/alpine-glibc:alpine-3.9 dockerfile是不够的,因为在创建映像时可能有所不同。

2 个答案:

答案 0 :(得分:2)

您正确的说,通过摘要提取的图像实际上是(!)不变的。

图像摘要是从构成图像的层计算得出的SHA-256哈希。因此,不同的图像共享相同的摘要是极不可能的。

创建图像后,图层不会更改。因此,即使FROM图片已更改,您现有的图片也不会被更改。

但是,如果您使用新的(标记相同的)FROM图像重建图像,则图像的摘要将发生变化,这将向您发出信号,表明情况已经发生变化。

也可以(并且是一种很好的做法)在FROM语句中使用摘要(出于您引用的原因),但是很少有开发人员这样做。您可能希望确保Dockerfiles语句中的FROM使用摘要,以确保始终使用相同的图像源。

但是,由于它一直都是乌龟,所以您递归地将信任委托给从中一直导出到SCRATCH的图像。

这是推荐使用图像漏洞工具的原因之一。

我最近为自己的教育探索了这一点:

https://medium.com/google-cloud/adventures-w-docker-manifests-78f255d662ff

答案 1 :(得分:0)

docker image history似乎可以帮助您识别出这种变化。

以下是标签上的完整示例,并以摘要为例:

$ docker image history --no-trunc 34982ce484b5
IMAGE                                                                     CREATED             CREATED BY                                              SIZE                COMMENT
sha256:34982ce484b5d709bffb6bf8cca2163ff9231d1a900305f888a5baf59a3414cd   4 weeks ago         /bin/sh -c CONDA_VERSION="4.5.12" &&     CONDA_MD5_CHECKSUM="866ae9dff53ad0874e1d1a60b1ad1ef8" &&         apk add --no-cache --virtual=.build-dependencies wget ca-certificates bash &&         mkdir -p "$CONDA_DIR" &&     wget "http://repo.continuum.io/miniconda/Miniconda3-${CONDA_VERSION}-Linux-x86_64.sh" -O miniconda.sh &&     echo "$CONDA_MD5_CHECKSUM  miniconda.sh" | md5sum -c &&     bash miniconda.sh -f -b -p "$CONDA_DIR" &&     echo "export PATH=$CONDA_DIR/bin:\$PATH" > /etc/profile.d/conda.sh &&     rm miniconda.sh &&         conda update --all --yes &&     conda config --set auto_update_conda False &&     rm -r "$CONDA_DIR/pkgs/" &&         apk del --purge .build-dependencies &&      mkdir -p "$CONDA_DIR/locks" &&     chmod 777 "$CONDA_DIR/locks"                                              190MB
<missing>                                                                 4 weeks ago         /bin/sh -c #(nop)ENV PATH=/opt/conda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin                                              0B
<missing>                                                                 4 weeks ago         /bin/sh -c #(nop)ENV CONDA_DIR=/opt/conda                                              0B
<missing>                                                                 6 weeks ago         /bin/sh -c ALPINE_GLIBC_BASE_URL="https://github.com/sgerrand/alpine-pkg-glibc/releases/download" &&     ALPINE_GLIBC_PACKAGE_VERSION="2.29-r0" &&     ALPINE_GLIBC_BASE_PACKAGE_FILENAME="glibc-$ALPINE_GLIBC_PACKAGE_VERSION.apk" &&     ALPINE_GLIBC_BIN_PACKAGE_FILENAME="glibc-bin-$ALPINE_GLIBC_PACKAGE_VERSION.apk" &&     ALPINE_GLIBC_I18N_PACKAGE_FILENAME="glibc-i18n-$ALPINE_GLIBC_PACKAGE_VERSION.apk" &&     apk add --no-cache --virtual=.build-dependencies wget ca-certificates &&     echo         "-----BEGIN PUBLIC KEY-----        MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApZ2u1KJKUu/fW4A25y9m        y70AGEa/J3Wi5ibNVGNn1gT1r0VfgeWd0pUybS4UmcHdiNzxJPgoWQhV2SSW1JYu        tOqKZF5QSN6X937PTUpNBjUvLtTQ1ve1fp39uf/lEXPpFpOPL88LKnDBgbh7wkCp        m2KzLVGChf83MS0ShL6G9EQIAUxLm99VpgRjwqTQ/KfzGtpke1wqws4au0Ab4qPY        KXvMLSPLUp7cfulWvhmZSegr5AdhNw5KNizPqCJT8ZrGvgHypXyiFvvAH5YRtSsc        Zvo9GI2e2MaZyo9/lvb+LbLEJZKEQckqRj4P26gmASrZEPStwc+yqy1ShHLA0j6m        1QIDAQAB        -----END PUBLIC KEY-----" | sed 's/   */\n/g' > "/etc/apk/keys/sgerrand.rsa.pub" &&     wget         "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BASE_PACKAGE_FILENAME"         "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BIN_PACKAGE_FILENAME"         "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" &&     apk add --no-cache         "$ALPINE_GLIBC_BASE_PACKAGE_FILENAME"         "$ALPINE_GLIBC_BIN_PACKAGE_FILENAME"         "$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" &&         rm "/etc/apk/keys/sgerrand.rsa.pub" &&     /usr/glibc-compat/bin/localedef --force --inputfile POSIX --charmap UTF-8 "$LANG" || true &&     echo "export LANG=$LANG" >/etc/profile.d/locale.sh &&         apk del glibc-i18n &&         rm "/root/.wget-hsts" &&     apk del .build-dependencies &&     rm         "$ALPINE_GLIBC_BASE_PACKAGE_FILENAME"         "$ALPINE_GLIBC_BIN_PACKAGE_FILENAME"      "$ALPINE_GLIBC_I18N_PACKAGE_FILENAME"   6.71MB
<missing>                                                                 6 weeks ago         /bin/sh -c #(nop)ENV LANG=C.UTF-8                                              0B
<missing>                                                                 8 weeks ago         /bin/sh -c #(nop)CMD ["/bin/sh"]                                              0B
<missing>                                                                 8 weeks ago         /bin/sh -c #(nop) ADD file:2a1fc9351afe35698918545b2d466d9805c2e8afcec52f916785ee65bbafeced in /                                              5.53MB

在输出的第四行,我可以看到6周前,该图像似乎已被以ALPINE_GLIBC_BASE_URL=...开头的shell命令更改,而该命令正是该命令的第一个RUN命令parent image

因此,的确,在这里您可以看到此图像随时间而改变。

但是,这对您来说很重要:您还可以看到Docker映像由其父映像的RUN组成,而不是 >包含对它的任何引用(您也可以运行docker image inspect [image_digest],仔细检查一下)。

意味着docker将图像的各个部分压缩在一起,并首先提取出创建该图像的命令的摘要,而不是因为FROM并没有变化,而底层图像却发生了变化。

因此,考虑到这一点并参考this other answer about digest,我非常怀疑如果您更改FROM图像,则摘要将不会相同,这意味着您仍然在这种情况下受到保护。