Docker COPY与文件夹通配符

时间:2017-08-20 19:27:38

标签: docker dockerfile

给定这样的文件结构:

project root
|-- X.sln
|-- src
|    |-- Foo
|    |    |-- Foo.fsproj
|    |    |-- Foo.fs
|    |-- Bar
|         |-- Bar.fsproj
|         |-- Bar.fs
|-- test
     |-- Baz
          |-- Baz.fsproj

我想首先将所有.fsproj个文件添加到我的Docker镜像中,然后运行命令,然后添加其余文件。我尝试了以下内容,但of course it didn't work

COPY X.sln .
COPY **/*.fsproj .
RUN dotnet restore
COPY . .
RUN dotnet build

这个想法是在前两个COPY步骤之后,图像上的文件树是这样的:

working dir
|-- X.sln
|-- src
|    |-- Foo
|    |    |-- Foo.fsproj
|    |-- Bar
|         |-- Bar.fsproj
|-- test
     |-- Baz
          |-- Baz.fsproj

,树的其余部分仅在 RUN dotnet restore后的中添加。

有没有办法模仿这种行为,最好不要诉诸scripts outside of the dockerfile

3 个答案:

答案 0 :(得分:1)

您可以使用两个RUN命令来解决此问题,方法是使用shell命令(find,sed和xargs)。

执行以下步骤:

  1. 查找所有fsproj文件,使用正则表达式提取不带扩展名的文件名,使用xargs使用此数据创建带有mkdir的目录;
  2. 基于先前的脚本,更改正则表达式以创建从头到尾的语法,并使用mv命令将文件移动到新创建的文件夹中。

示例:

    COPY *.sln ./
    COPY */*.fsproj ./
    RUN find *.fsproj | sed -e 's/.fsproj//g' | xargs mkdir
    RUN find *.fsproj | sed -r -e 's/((.+).fsproj)/.\/\1 .\/\2/g' | xargs -I % sh -c 'mv %'

参考文献:

how to use xargs with sed in search pattern

答案 1 :(得分:0)

一种无需借助Dockerfile外部脚本即可用于实现所需功能的模式是:

    COPY <project root> .    
    RUN <command to tar/zip the directory to save a copy inside the container> \
         <command the removes all the files you don't want> \
         dotnet restore \
         <command to unpack tar/zip and restore the files> \
         <command to remove the tar/zip> \
         dotnet build

这会将您的所有操作保留在容器内。我将它们全部捆绑在一个RUN命令中,以将所有活动保持在构建的单个层中。您可以根据需要将其拆分。

这只是Linux上的一个示例,该示例介绍如何递归删除所有不需要的文件:https://unix.stackexchange.com/a/15701/327086。根据您的示例,我的假设是对您而言这将不是一项昂贵的操作。

答案 2 :(得分:0)

如果您使用 dotnet 命令来管理您的解决方案,您可以使用这段代码:

  1. 将解决方案和所有项目文件复制到 WORKDIR
  2. 使用 dotnet sln list
  3. 列出解决方案中的项目
  4. 迭代项目列表并将相应的 *proj 文件移动到新创建的目录中。
COPY *.sln ./
COPY */*/*.*proj ./
RUN dotnet sln list | \
      tail -n +3 | \
      xargs -I {} sh -c \
        'target="{}"; dir="${target%/*}"; file="${target##*/}"; mkdir -p -- "$dir"; mv -- "$file" "$target"'