Dockerfile复制并保留文件夹结构。

7

我想创建一个Dockerfile,将所有的package.json文件复制到镜像中,但保留文件夹结构。

以下是我的代码:

FROM node:15.9.0-alpine as base
WORKDIR /app/
COPY ./**/package.json ./
CMD ls -laR /app

运行命令: sudo docker run --rm -it $(sudo docker build -q .)

但它只会复制一个package.json文件并将其放置在根目录(/app)中。

这是我正在进行测试的目录:

├── Dockerfile
├── t1
│   └── package.json
└── t2
    └── ttt
        ├── b.txt
        └── package.json

我希望它在容器内看起来像这样:

├── Dockerfile
├── t1
│   └── package.json
└── t2
    └── ttt
        └── package.json
2个回答

4
Dockerfile中COPY指令的文档中指出使用Go filepath.Match函数进行glob扩展。但该函数仅支持基本通配符*?[a-z],而不支持像一些shell支持的**等扩展字符。
由于COPY仅接受文件名glob作为输入,并且它喜欢扁平化文件结构,因此我认为没有办法在单个命令中进行选择性复制。
相反,您需要列出要复制的单个文件。 COPY将根据需要创建目录,但这意味着您需要在COPY的两侧重复路径。
COPY t1/package*.json t1/
COPY t2/ttt/package*.json t2/ttt/

我可以想象使用多阶段构建的某些hacky方法;有一个初始阶段,复制整个源树,然后删除除了package*.json之外的所有文件,然后将其复制到实际构建阶段。我会先考虑将我的存储库拆分成较小的模块,并为每个模块使用单独的Dockerfile。

感谢您的评论。如果我复制所有源代码并删除,我认为我将失去npm install缓存。在我的仓库中,我使用lerna和lerna-dockerize创建一个单一的Dockerfile,并为每个包创建构建阶段。但是我想在第一个阶段安装所有依赖项,这样我就不需要在每个微服务中重新下载它们。 - CY-OD
这就是单独的构建阶段可能发挥作用的地方:如果您 COPY --from=an-earlier-stage 并且复制的特定文件未被修改,则不会使缓存失效。虽然我没有尝试过这种方法。 - David Maze

3

经过大量搜索,我终于找到了适合我的解决方案

最终我创建了一个包含所有package.json文件的tar文件

tar --exclude node_modules -cf package.json.tar  */package.json

使用docker add命令在镜像内解压该tar文件

ADD package.json.tar .

add 命令将检测输入是否为 tar 文件,并将其解压缩到镜像内部。

使用此方法的缺点是您必须在构建镜像之前有时运行 tar 命令。


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