Docker缓存-即使我删除了.git repo,构建还是很大的

Docker缓存-即使我删除了.git repo,构建还是很大的,docker,dockerfile,Docker,Dockerfile,我在Dockerfile中运行了以下步骤: RUN git clone my-repo # step 1 RUN some other stuff # step 2 RUN rm -rf 'my-repo/.git' # step 3 我原以为这会减少docker映像的大小,但它似乎没有-因为步骤1是一个无法通过步骤3缩小的层?每个运行步骤都会在临时容器内执行一个命令,并且从该命令生成的文件系统更改会被捕获为一个不可变的层。该层可能包含删除前一层中文件的指令,但这

我在Dockerfile中运行了以下步骤:

RUN git clone my-repo       # step 1
RUN some other stuff        # step 2
RUN rm -rf 'my-repo/.git'   # step 3

我原以为这会减少docker映像的大小,但它似乎没有-因为步骤1是一个无法通过步骤3缩小的层?

每个
运行
步骤都会在临时容器内执行一个命令,并且从该命令生成的文件系统更改会被捕获为一个不可变的层。该层可能包含删除前一层中文件的指令,但这些文件不会从前一层中删除,因为它们是不可变的,并且可能在其他图像中重复使用。例如,您可以从创建的图像中删除alpine或debian base图像中的文件,而这不会破坏从这些图像中创建的所有其他图像

因此,设计DockerFile时的最佳实践是删除创建这些文件的同一步骤中的任何临时文件。您经常会看到通过链接命令来完成此操作,如:

RUN git clone my-repo \
 && echo some other stuff \
 && rm -rf 'my-repo/.git'

每个
RUN
步骤都将在一个临时容器内执行一个命令,该命令产生的文件系统更改被捕获为一个不可变层。该层可能包含删除前一层中文件的指令,但这些文件不会从前一层中删除,因为它们是不可变的,并且可能在其他图像中重复使用。例如,您可以从创建的图像中删除alpine或debian base图像中的文件,而这不会破坏从这些图像中创建的所有其他图像

因此,设计DockerFile时的最佳实践是删除创建这些文件的同一步骤中的任何临时文件。您经常会看到通过链接命令来完成此操作,如:

RUN git clone my-repo \
 && echo some other stuff \
 && rm -rf 'my-repo/.git'

正如@BMitch所解释的,docker层机制就是这样工作的。从以前的图层中删除文件并不会减少图像大小,因为图层数据是不可变的,实际上并没有删除。因此,一个选项是在同一个
RUN
命令中链接多个操作

另一个选项,根据步骤2中命令的性质,您可能需要使用

其概念是将构建过程分为多个阶段,每个阶段可能来自不同的映像,您可以只使用前一阶段中感兴趣的资源,而无需继承前一层的大小开销

例如,如果您的git repo包含一个生成
.war
的maven项目,并且您的目标是在docker容器上的应用服务器中部署此
war
,则Dockerfile可以如下所示:

FROM some_image_with_maven_installed AS builder
RUN git clone my-repo 
WORKDIR my_repo_dir
RUN mvn clean package

FROM some_image_with_app_server_installed
WORKDIR app_server_deployment_dir
COPY --from=builder /path_to_war/app.war .
RUN start_server
....
因此,您只需将
war
文件复制到服务器,就可以丢弃builder阶段的所有内容


如果您像@BMitch解释的那样定义
步骤2

的性质,我可以更具体地说明您的情况,这就是docker层机制的工作方式。从以前的图层中删除文件并不会减少图像大小,因为图层数据是不可变的,实际上并没有删除。因此,一个选项是在同一个
RUN
命令中链接多个操作

另一个选项,根据步骤2中命令的性质,您可能需要使用

其概念是将构建过程分为多个阶段,每个阶段可能来自不同的映像,您可以只使用前一阶段中感兴趣的资源,而无需继承前一层的大小开销

例如,如果您的git repo包含一个生成
.war
的maven项目,并且您的目标是在docker容器上的应用服务器中部署此
war
,则Dockerfile可以如下所示:

FROM some_image_with_maven_installed AS builder
RUN git clone my-repo 
WORKDIR my_repo_dir
RUN mvn clean package

FROM some_image_with_app_server_installed
WORKDIR app_server_deployment_dir
COPY --from=builder /path_to_war/app.war .
RUN start_server
....
因此,您只需将
war
文件复制到服务器,就可以丢弃builder阶段的所有内容

如果您定义
步骤2
的性质,我可以更具体地说明您的情况