不使用.dockerignore从docker构建COPY指令中排除一个文件夹

7

我有一个代码库,想要为其构建镜像。其中有多个文件夹,我想要排除名为“solver”的文件夹。但是使用dockerignore文件不是一个选项。

我尝试了:

COPY ./[(^solver)] ./
COPY ./[(^solver)]* ./
COPY ./[^solver] ./

然而这些并没有起作用。

这篇文章中的第二个解决方案并不能解决我的问题。

2个回答

1
只要不使用 .dockerignore 选项,就有三种方法可以使用:
  1. 通过多个复制指令(每个字母一个)从 COPY 中排除文件夹:

     COPY ./file_that_always_exists.txt ./[^s]* .        # 所有不以 's' 开头的文件
     COPY ./file_that_always_exists.txt ./s[^o]* .       # 所有以 's' 开头但不是以 'so' 开头的文件
     COPY ./file_that_always_exists.txt ./so[^l]* .      # 所有以 'so' 开头但不是以 'sol' 开头的文件
     COPY ./file_that_always_exists.txt ./sol[^v]* .     # 所有以 'sol' 开头但不是以 'solv' 开头的文件
     COPY ./file_that_always_exists.txt ./solv[^e]* .    # 所有以 'solv' 开头但不是以 'solve' 开头的文件
     COPY ./file_that_always_exists.txt ./solve[^r]* .   # 所有以 'solve' 开头但不是以 'solver' 开头的文件
    

    缺点:这将扁平化文件夹结构,而且如果你需要对多个文件夹进行操作,那就更麻烦了 :(

    请注意,file_that_always_exists.txt 的要求(例如可以是 Dockerfile)是为了避免在没有匹配复制步骤的文件时出现错误 COPY failed: no source files were specified

  2. 复制所有文件夹,然后在不同的层中删除不需要的文件夹:

     COPY . .
     RUN rm -rf ./solver
    

    缺点:文件夹的内容仍然会在 Docker 镜像中可见,如果你想要减小镜像大小,这并没有帮助。

  3. 手动指定要复制的文件和文件夹:

     COPY ["./file_to_copy_1.ext", "file_to_copy_2.ext", "file_to_copy_3.ext", "."]
     COPY ./folder_to_copy_1/ ./folder_to_copy_1/
     # ...
     COPY ./folder_to_copy_n/ ./folder_to_copy_n/
    

    缺点:你必须手动编写所有文件和文件夹,并且更麻烦的是,当文件夹层次结构发生变化时,必须手动更新列表。

每种方法都有其优缺点,选择最符合您应用需求的方法。

关于问题 #2,当你说“文件夹的内容在Docker镜像中仍然可见”时,你是指在 RUN rm -rf ./solver 执行之前的几分之一秒内可见吗? - k1eran
1
@k1eran 我的意思是它将在一个不同的层级中,这样任何检查镜像的人都可以看到它,而且你也不会节省空间。 - Yogev Neumann

0
你可以使用绑定挂载:
FROM rockylinux:9
RUN --mount=type=bind,target=/_src \
    tar -c -C /_src --exclude '*/solver/*' . | tar -x -C /opt/app/src; \
    : ;

或者在相同的RUN中查找并删除,因为它不会留下任何垃圾。
FROM rockylinux:9
RUN --mount=type=bind,target=/_src \
    tar -c -C /_src . | tar -x -C /opt/app/src; \
    find /opt/app/src -type d -name "solver" -exec rm --recursive --force {}; \
    : ;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接