有没有更优雅的方法可以使用Docker COPY将特定文件复制到工作目录?

时间:2018-07-17 03:25:59

标签: docker .net-core dockerfile

尝试使用microsoft / dotnet:2.1-aspnetcore-runtime创建容器。 .net核心解决方案文件在解决方案下嵌套了多个项目,每个项目都有自己的.csproj文件。我正在尝试为子项目创建更优雅的COPY指令

https://github.com/dotnet/dotnet-docker/tree/master/samples/aspnetapp处的示例包含一个只有一个.csproj的解决方案文件,因此可以创建Dockerfile:

COPY *.sln .
COPY aspnetapp/*.csproj ./aspnetapp/
RUN dotnet restore

以这种方式工作

COPY my_solution_folder/*.sln .
COPY my_solution_folder/project/*.csproj my_solution_folder/
COPY my_solution_folder/subproject_one/*.csproj subproject_one/
COPY my_solution_folder/subproject_two/*.csproj subproject_two/
COPY my_solution_folder/subproject_three/*.csproj subproject_three/

对于以下解决方案文件夹结构:

my_solution_folder\my_solution.sln
my_solution_folder\project\my_solution.csproj
my_solution_folder\subproject_one\subproject_one.csproj
my_solution_folder\subproject_two\subproject_two.csproj
my_solution_folder\subproject_three\subproject_three.csproj

但这不是(是一个随机的猜测)

COPY my_solution_folder/*/*.csproj working_dir_folder/*/

有没有更优雅的解决方案?

4 个答案:

答案 0 :(得分:4)

考虑到COPY(moby issue 15858)不能很好地支持通配符,您可以:

  • 尝试在不想复制的文件夹中添加.dockerignore文件(同时排除您想要的文件夹):这很麻烦
  • 或以shown here的形式创建所需的所有文件夹的tar文件

以下是一个示例,适合您的情况:

find .. -name '*.csproj' -o -name 'Finomial.InternalServicesCore.sln' -o -name 'nuget.config' \
  | sort | tar cf dotnet-restore.tar -T - 2> /dev/null

使用包含以下内容的Dockerfile

ADD docker/dotnet-restore.tar ./

这个想法是:存档会自动使用ADD进行扩展。


OP sturmstrike提到in the comments中的Optimising ASP.NET Core apps in Docker - avoiding manually copying csproj files (Part 2)Andrew Lock "Sock"

  

该替代解决方案实际上使用了我先前不使用的通配符技术,但是对您的项目结构,两阶段方法以及一些巧妙的bash工作进行了一些假设,以解决通配符的局限性。

     

我们将平面显示csproj文件列表,然后将其移回嵌套在src子文件夹中的正确位置。

# Copy the main source project files
COPY src/*/*.csproj ./  
RUN for file in $(ls *.csproj); do mkdir -p src/${file%.*}/ && mv $file src/${file%.*}/; done

L01nl建议in the comments不需要压缩的另一种方法:“ Optimising ASP.NET Core apps in Docker - avoiding manually copying csproj files”,来自Andrew Lock "Sock"

FROM microsoft/aspnetcore-build:2.0.6-2.1.101 AS builder
WORKDIR /sln

COPY ./*.sln ./NuGet.config  ./

# Copy the main source project files
COPY src/*/*.csproj ./
RUN for file in $(ls *.csproj); do mkdir -p src/${file%.*}/ && mv $file src/${file%.*}/; done

# Copy the test project files
COPY test/*/*.csproj ./
RUN for file in $(ls *.csproj); do mkdir -p test/${file%.*}/ && mv $file test/${file%.*}/; done

RUN dotnet restore

# Remainder of build process
  

此解决方案比我以前基于tar的工作要干净得多,因为它不需要任何外部脚本,只需标准的docker COPYRUN命令即可​​。
  通过首先跨csproj目录中的src个文件复制,将它们移动到正确的位置,然后跨测试项目文件进行复制,可以解决通配符问题。

答案 1 :(得分:2)

除了VonC的答案(是正确的)之外,我还从Windows 10操作系统构建并针对Linux容器。相当于使用Windows和7z(无论如何我通常都已安装)的上述答案是:

7z a -r -ttar my_project_files.tar .\*.csproj .\*.sln .\*nuget.config

接着是Dockerfile中的ADD进行解压缩。

请注意,安装7-zip后,您需要将安装文件夹添加到您的环境路径中,以上述方式进行调用。

查看moby issue 15858,您将看到执行BASH脚本以生成tar文件,然后执行使用ADD提取的Dockerfile的后续执行。

完全自动化批处理,或使用下面示例中给出的Powershell执行。

Pass PowerShell variables to Docker commands

答案 2 :(得分:2)

要考虑的另一种选择是使用多阶段构建来预过滤/准备所需的文件。这是mentioned on the same moby issue 15858

对于那些基于.NET Framework的用户,您可以更进一步,并利用robocopy

例如:

=$A1<>$B1

这里的最大优点是,无需对解决方案的结构做任何假设。 robocopy的“ / s”标志将为您保留任何目录结构。

请注意,那里的'/ ndl / njh / njs'标志只是为了减少对数噪声。

答案 3 :(得分:1)

另一个解决方案,可能会慢一些,但合而为一

一个文件和一个命令docker build .

中的所有内容

我将Dockerfile分为两步,

  • 第一个将* .csproj文件压缩的​​图像
  • 第二张图片使用tar和设置项目

代码:

FROM ubuntu:18.04 as tar_files
WORKDIR /tar
COPY . .
RUN find . -name "*.csproj" -print0 | tar -cvf projectfiles.tar --null -T -


FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /source

# copy sln
COPY *.sln .

# Copy all the csproj files from previous image
COPY --from=tar_files /tar/projectfiles.tar .
RUN tar -xvf projectfiles.tar
RUN rm projectfiles.tar

RUN dotnet restore

# Remainder of build process