Docker:WORKDIR 创建一个层?

홍한석*_*홍한석 2 docker dockerfile

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#minimize-the-number-of-layers

\n

阅读上述文档后,我进行了测试以证明以下说法:

\n
\n

只有 RUN、COPY、ADD 指令才能创建层。其他指令创建临时中间映像,并且不会增加构建的大小。

\n
\n

我的环境是:

\n
\xe2\x9d\xaf sw_vers\nProductName:    macOS\nProductVersion: 11.6.1\nBuildVersion:   20G224\n\n\xe2\x9d\xaf docker version\nClient:\n Cloud integration: v1.0.22\n Version:           20.10.13\n API version:       1.41\n Go version:        go1.16.15\n Git commit:        a224086\n Built:             Thu Mar 10 14:08:44 2022\n OS/Arch:           darwin/amd64\n Context:           default\n Experimental:      true\n\nServer: Docker Desktop 4.6.1 (76265)\n Engine:\n  Version:          20.10.13\n  API version:      1.41 (minimum version 1.12)\n  Go version:       go1.16.15\n  Git commit:       906f57f\n  Built:            Thu Mar 10 14:06:05 2022\n  OS/Arch:          linux/amd64\n  Experimental:     false\n containerd:\n  Version:          1.5.10\n  GitCommit:        2a1d4dbdb2a1030dc5b01e96fb110a9d9f150ecc\n runc:\n  Version:          1.0.3\n  GitCommit:        v1.0.3-0-gf46b6ba\n docker-init:\n  Version:          0.19.0\n  GitCommit:        de40ad0\n\n\xe2\x9d\xaf dive --version\ndive 0.10.0\n# installed from brew\n
Run Code Online (Sandbox Code Playgroud)\n

遵循 Dockerfile,用于测试,包含所有指令,但它没有悄悄的意义(其中一些没有使用,所以它可能没有涵盖所有可能性):

\n
# syntax=docker/dockerfile:1\nFROM alpine:3.15.4\nLABEL name=layer\nEXPOSE 3456\nENV APP=layer\nADD add.tar.gz /\nCOPY copy /copy\nENTRYPOINT ["date"]\nRUN rm /bin/arch\nCMD ["--help"]\nVOLUME /log\nUSER root\nARG workdir\nWORKDIR $workdir\nONBUILD RUN echo \'b\'\nSTOPSIGNAL SIGTERM\nHEALTHCHECK CMD which date\nSHELL ["/bin/sh", "-c"]\n
Run Code Online (Sandbox Code Playgroud)\n

构建并检查图像,名称为layer,它有 5 层:

\n
# syntax=docker/dockerfile:1\nFROM alpine:3.15.4\nLABEL name=layer\nEXPOSE 3456\nENV APP=layer\nADD add.tar.gz /\nCOPY copy /copy\nENTRYPOINT ["date"]\nRUN rm /bin/arch\nCMD ["--help"]\nVOLUME /log\nUSER root\nARG workdir\nWORKDIR $workdir\nONBUILD RUN echo \'b\'\nSTOPSIGNAL SIGTERM\nHEALTHCHECK CMD which date\nSHELL ["/bin/sh", "-c"]\n
Run Code Online (Sandbox Code Playgroud)\n

使用 进行检查dive,有意外的指令会生成图层,FROM并且WORKDIR

\n
# Preparation: create build contexts for ADD and COPY\n> mkdir add\n> dd if=/dev/urandom of=add/1 bs=1M count=1\n> dd if=/dev/urandom of=add/2 bs=1M count=1\n> dd if=/dev/urandom of=copy bs=1M count=1\n> tar -cf add.tar add\n> gzip add.tar\n\n# Build\n\xe2\x9d\xaf docker build --build-arg workdir=/etc -t layer .\n(...eliding)\n\n# Inspect\n\xe2\x9d\xaf docker inspect layer | jq \'.[0].RootFS.Layers | length\'\n5\n\n
Run Code Online (Sandbox Code Playgroud)\n

除了RUN、ADD、COPY之外,还有其他创建镜像层的指令吗?

\n
    \n
  • 对于 FROM 来说,这似乎是合理的
  • \n
  • 但对于 WORKDIR,为什么呢?我可以得到有关它的参考资料吗?
  • \n
\n

+ 比如dive,我如何在图像层摘要和命令之间进行映射?

\n
# the left pane of `dive layer\'\n\xe2\x94\x83  \xe2\x97\x8f  Layers \xe2\x94\xa3 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x81 \xe2\x94\x82\nCmp   Size  Command                                                   \n    5.6 MB  FROM 8792aa27a60beb9                                       \n    2.1 MB  ADD add.tar.gz / # buildkit                                \n    1.0 MB  COPY copy /copy # buildkit                                 \n       0 B  RUN /bin/sh -c rm /bin/arch # buildkit                     \n       0 B  WORKDIR /etc\n
Run Code Online (Sandbox Code Playgroud)\n
\n

更新

\n

经过多次重建图像后,除了WORKDIR之外,它还有4层。似乎不确定...:

\n
\xe2\x9d\xaf docker inspect layer | jq \'.[0].RootFS.Layers[]\'\n"sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628"\n"sha256:38df8fd6b1d0100d029b0cfa3611ee48cf2d0e2d71856dab9b3c818ae180e100"\n"sha256:deab9dc570f38644bbad2bb4a9a91ecec8afdbd4dbd7ed3bae4c3c63e84b1924"\n"sha256:34b91600d244859b8ce5aaf493bed6c778c933d51d7f72df7f9ab426f55d50db"\n"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"\n\n
Run Code Online (Sandbox Code Playgroud)\n

Dan*_*owe 5

这似乎是最佳实践文档中的文档“错误”。更好的表达方式是,只有您提到的那些命令才会创建增加总构建大小的层。

请注意,您看到的层是 0 字节,而不是 FROM、ADD、COPY,每个层都有关联的大小(它们对文件系统总增长的贡献量)。

Cmp   Size  Command                                                   
    5.6 MB  FROM 8792aa27a60beb9                                       
    2.1 MB  ADD add.tar.gz / # buildkit                                
    1.0 MB  COPY copy /copy # buildkit                                 
       0 B  RUN /bin/sh -c rm /bin/arch # buildkit                     
       0 B  WORKDIR /etc
Run Code Online (Sandbox Code Playgroud)

WORKDIR 存在一个层 - 但它是元数据。该rm命令存在一个层,但它添加的只是“文件已删除”标记 - 而不是实际的文件内容。因此它们对映像中的最终文件系统大小没有任何贡献。

至于 FROM,它本身并不创建一个图层 - 它导入一个起始图像。我想,参考文献可能会更清楚地说明这一点,但无论哪种方式都会让某人感到困惑。他们必须假设 FROM 对大小的影响是显而易见的(除非您使用的是FROM scratch)。

我无法找到关于此的明确参考。阅读源代码可能是唯一可用的此类参考。