当前位置: 首页 > 知识库问答 >
问题:

环境,运行生成层,图像或容器?(理解文件问题)

司徒池暝
2023-03-14

我搜索了站点:stackoverflow。com dockerfile:ENV,RUN-layers或images并读取Docker EXPOSE是否创建新层?什么是Docker图像“层”?。

在阅读文档编写Dockerfile的最佳实践并试图理解这一部分时:

每个环境线都会创建一个新的中间层,就像运行命令一样。这意味着,即使在将来的层中取消设置环境变量,它仍会在该层中保持,并且可以转储其值。

我回顾了上述部分:

在旧版本的Docker中,重要的是最小化图像中的层数,以确保它们的性能。添加了以下功能以减少此限制:

只有运行、复制、添加和创建层的说明。其他说明会创建临时中间映像,并且不会增加生成的大小。

我读过如何在dockerfile中取消设置ENV?。并重新做了文档页上给出的例子,它确实证明了ENV没有取消设置:

$ docker build -t alpine:envtest -<<HITHERE
> FROM alpine
> ENV ADMIN_USER="mark"
> RUN unset ADMIN_USER
> HITHERE
Sending build context to Docker daemon  3.072kB
Step 1/3 : FROM alpine
latest: Pulling from library/alpine
89d9c30c1d48: Already exists 
Digest: sha256:c19173c5ada610a5989151111163d28a67368362762534d8a8121ce95cf2bd5a
Status: Downloaded newer image for alpine:latest
 ---> 965ea09ff2eb
Step 2/3 : ENV ADMIN_USER="mark"
 ---> Running in 5d34f829a387
Removing intermediate container 5d34f829a387
 ---> e9c50b16c0e1
Step 3/3 : RUN unset ADMIN_USER
 ---> Running in dbcf57ca390d
Removing intermediate container dbcf57ca390d
 ---> 2cb4de2e0257
Successfully built 2cb4de2e0257
Successfully tagged alpine:envtest
$ docker run --rm alpine:envtest sh -c 'echo $ADMIN_USER'
mark

对于ENVRUN,输出显示相同的“删除中间容器”。我最近下载了docker,不要认为它太旧了:

$ docker --version
Docker version 19.03.5, build 633a0ea

也许RUN指令RUN命令是另一回事
ENVRUN-他们是否创建图层、图像或容器?

共有1个答案

轩辕实
2023-03-14

作为容器化系统的Docker基于图像和容器的两个主要概念。它们之间的主要区别是顶部可写层。当您生成一个新的容器时,新的可写层将放在最后一个图像层的上方。该层通常被称为容器层。

所有基础图像内容保持不变,并且正在运行的容器中的每个更改(创建新文件、修改现有文件等)都将复制到此薄可写层中。

在这种情况下,Docker只存储实际的容器数据和一个映像实例,这减少了存储使用并简化了底层工作流。我将它与C语言中的静态和动态链接进行比较,所以Docker使用动态链接。

该图像由多个层组成。每一层只是它之前的层的一组差异。

留档说:

只有运行、复制、添加和创建层的说明。其他说明会创建临时中间映像,并且不会增加生成的大小。

这里的描述既不清楚也不准确,而且一般来说,不仅这些说明在Docker的最新版本中创建了层,文档如何概述。

例如,默认情况下,WORKDIR创建一个不存在的给定路径,并将目录更改为该路径。如果创建了新路径,WORKDIR将生成一个新层。

顺便说一下,ENV不会导致图层创建。数据将永久存储在映像和容器配置中,并且没有简单的方法来消除它。基本上,有两个选项,即如何组织工作流:

  • 临时环境变量,在当前RUN指令结束之前,这些变量都可用:
RUN export NAME='megatron' && echo $NAME # 'megatron'
RUN echo $NAME # blank
  • 清洁环境变量,如果没有环境或空白内容对你来说没有区别,那么你可以这样做:
ENV NAME='megatron'
# some instructions
ENV NAME=''
RUN echo $NAME

在Docker的上下文中,命令和指令之间没有区别。对于RUN,任何不改变文件系统内容的命令都不会触发永久层创建。考虑以下Dockerfile

FROM alpine:latest
RUN echo "Hello World" # no layer
RUN touch file.txt # new layer
WORKDIR /no/existing/path # new layer

最后,产出将是:

Step 1/4 : FROM alpine:latest
 ---> 965ea09ff2eb
Step 2/4 : RUN echo "Hello World"
 ---> Running in 451adb70f017
Hello World
Removing intermediate container 451adb70f017
 ---> 816ccbd1e8aa
Step 3/4 : RUN touch file.txt
 ---> Running in 9edc6afdd1e5
Removing intermediate container 9edc6afdd1e5
 ---> ea0040ec0312
Step 4/4 : WORKDIR /no/existing/path
 ---> Running in ec0feaf6710d
Removing intermediate container ec0feaf6710d
 ---> f2fe46478f7c
Successfully built f2fe46478f7c
Successfully tagged envtest:lastest

inspect命令用于检查Docker对象:

docker inspect --format='{{json .RootFS.Layers}}' <image_id>

这向我们展示了三个层的SHA列表,包括从、第二次运行和WORKDIR指令,我建议使用dive来探索docker图像中的每个层。

那个么为什么它说移除中间容器而不移除中间层呢?实际上,要执行RUN命令,Docker需要实例化一个包含中间映像的容器,直到Dockerfile的那一行,然后运行实际的命令。然后,它将容器的状态作为新的中间映像“提交”,并继续构建过程。

 类似资料:
  • 本文向大家介绍生产环境中安全运行Docker容器,包括了生产环境中安全运行Docker容器的使用技巧和注意事项,需要的朋友参考一下 在生产环境中,强化Docker容器的一种方法就是使它们不可变,也就是只读。安全地运行容器的其他方法还包括最小化受攻击面和应用Linux安全过程,标准Linux安全过程和针对容器环境的特定过程都要应用。 在启动容器时传入--read-only标记就可以 在只读模式下运行

  • Compilation failure No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK? 试过配置Tomcat没有用,不知道那里出错了。希望大佬们能帮忙解决一下。

  • LEMP 是 PHP 网站应用的运行环境,也就是如果你打算在本地或者服务器上去运行一个用 PHP 语言写的网站应用,你需要为它搭建一个 LEMP 环境。

  • WordPress运行环境 PHP 5.2.4 或更新版本(不支持第三方推出的“PHP 6.0”) MySQL 5.0 或更新版本 Apache mod_rewrite 模块(可选,用于支持“固定链接”和“站点网络”功能) 什么是WampServer Wamp分别是Windows、Apache、Mysql和PHP的首字母,静态文件(例如后缀是.html的纯html)文件在操作系统上就可以运行,但用

  • 我最近才开始使用ImageJ(因此没有太多宏编程经验)来分析我的显微镜图片。为了生成FRET像素逐像素图像,这些图像被校正为光谱渗漏通过我使用的插件:像素。此插件需要3个图像的堆栈才能工作:FRET,捐助者,接受者。到目前为止,我必须自己打开每一张图片,这对于大时间堆栈来说真的很不方便( 我的数据结构的简短描述:工作文件夹\filename_t001c1(通道1图像-时间点001的捐助者),fil

  • 我在这里遵循拼图快速入门。我成功运行了给定的命令: 这将生成一个“运行时映像”,它是一个分解的目录结构,如下所示: 如何运行此功能?我期望的是一个二进制可执行文件,而不是分解的目录树。 bin目录有一个java和一个keytool。我什么也没看到。jar文件或。类文件以通过捆绑的java可执行文件运行。