我是Docker的新手。我的项目具有以下目录结构
docker-compose.yml
|-services
|-orders
|-DockerFile
我正在使用具有以下内容的标准ASP.Net Core DockerFile:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /src
COPY ["Services/Orders/Orders.csproj", "Services/Orders/"]
RUN dotnet restore "Services/Orders/Orders.csproj"
COPY . .
WORKDIR "/src/Services/Orders"
RUN dotnet build "Orders.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Orders.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Orders.dll"]
我的docker-compose.yml文件具有
# Please refer https://aka.ms/HTTPSinContainer on how to setup an https developer certificate for your ASP .NET Core service.
version: "3.4"
services:
orders-api:
image: orders-api
build:
context: .
dockerfile: Services/Orders/Dockerfile
ports:
- "2222:80"
我对这两个文件有些困惑
问题1:第2行的WORKDIR / app有什么用途?
我的理解是我们正在使用可以扩展的基本图像 当我们在第1行中导入基本图像,然后设置 第2和3行中的WORKDIR和端口,将被以下命令使用 使用这张图片?
问题2:为什么我们为SDK映像设置 WORKDIR / src ,而不是为 WORKDIR / app ?
>问题3:复制命令中的路径与Dockerfile或Docker-compose.yml文件相关吗?
在COPY [“ Services / Orders / Orders.csproj”,“ Services / Orders /”]行中,我们指定的路径似乎与docker-compose.yml文件相关,而不是与DockerFile相关。进一步嵌套在文件夹中。这是否意味着Dockerfile中的路径需要与docker-compose.yml相关?我之所以这样问,是因为我在想如果我使用此Dockerfile运行docker build命令,则会由于复制命令中的路径无效而收到错误消息。
答案 0 :(得分:1)
问题1:第2行的WORKDIR / app有什么用途?
这定义了您当前的工作目录。默认情况下,将从该位置运行以下命令,并且相对路径将从该位置开始。
具有以下文件结构的示例:
/app/
- README.md
- folder1/
- some.txt
WORKDIR /app
RUN ls
将打印
folder1
README.md
和
WORKDIR /app/folder1
RUN ls
将打印
some.txt
问题2:为什么要为SDK映像设置WORKDIR / src而不是WORKDIR / app?
请参阅问题1的答案。以下COPY
和dotnet restore
命令在/src
源目录中执行。 (构建是从/src
目录完成的,稍后在/app/publish
中创建的工件会被复制到最后一个阶段的/app
目录中,然后从该/app
目录执行)
问题3:复制命令中的路径与Dockerfile或Docker-compose.yml文件相关吗?
复制采用两条路径。第一个引用源(来自构建Docker镜像的上下文中的文件或文件夹),第二个引用目标(生成的Docker镜像中的文件顺序文件夹)。因此,这些路径通常仅特定于Dockerfile并且独立于您的docker-compose项目。
但是,在您的情况下,docker镜像构建的上下文是在docker-compose.yml中定义的:
build:
context: .
dockerfile: Services/Orders/Dockerfile
,因此您的docker映像映像构建的上下文似乎是docker-compose.yml所在的目录。如果仅在该文件夹中运行docker build -f Services/Orders/Dockerfile .
,则可以构建相同的映像。 (并非特定于docker-compose)
因此,您应该在docker-compose.yml所在目录的Orders.csproj
中找到./Services/Orders/
。然后在第二个构建阶段将此文件复制到/src/Services/Orders/Orders.csproj
。 (/src
可以在COPY
语句中提交,因为它是从当前工作目录开始的相对路径,该目录在上一行中定义。-请参阅问题1)
答案 1 :(得分:0)
对于以后进入该线程并遇到类似问题的任何人,我将根据Leo的答案和其他来源分享我到目前为止所学到的知识。
Docker具有称为 multi-stage 的功能。这使我们可以创建多个图层并使用它们。
可以使用不同的图像构建ASP.Net Core应用。 SDK 图像较大,但为我们提供了更多工具来在开发环境中构建和调试代码。
但是,在生产中,我们不需要SDK。我们只想利用PROD中的轻量级运行时间。我们可以利用Docker的多阶段构建功能来创建最终容器并使其轻量化。
来到Dockerfile ...
以“来自” 关键字开头的每个部分都定义了一个图层。在我最初的Dockerfile中,您可以看到我正在创建4个基础,构建,发布和最终层。我们可以命名一个图层,然后使用该名称在第一个图层的基础上创建一个新图层。
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 80
以上代码将基于aspnet:3.1映像创建一个名为“ base” 的层,该映像包含轻量级运行时,并将用于托管最终应用程序。 然后,将工作目录设置为 / app 文件夹,以便以后使用该层时,诸如 COPY 之类的命令将在此文件夹中运行。 接下来,我们仅公开端口80,这是Web服务器的默认端口。
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /src
COPY ["Services/Orders/Orders.csproj", "Services/Orders/"]
RUN dotnet restore "Services/Orders/Orders.csproj"
COPY . .
WORKDIR "/src/Services/Orders"
RUN dotnet build "Orders.csproj" -c Release -o /app/build
接下来,我们下载SDK映像,该映像将用于构建应用程序,并将此层称为“ build” 。 我们设置了以下“ COPY” 命令将使用的工作目录。
复制命令将文件从本地文件系统复制到容器中的指定位置。因此,基本上,我是将Orders.csproj文件复制到容器中,然后运行“ dotnet restore” 以还原该项目所需的所有Nuget软件包。
仅复制 .csproj 或 .sln 文件,然后在不复制整个代码的情况下还原NuGet软件包会更加有效,因为它利用了here所述的缓存是一种我不知道的被广泛采用的做法,想知道为什么我们不能简单地复制所有内容并只运行“ dotnet restore” 命令?
还原了NuGet软件包后,我们可以复制所有文件,然后运行“ dotnet build” 命令来构建我们的项目。
FROM build AS publish
RUN dotnet publish "Orders.csproj" -c Release -o /app/publish
嵌套,我们根据上一层“ build” 创建一个名为“ publish” 的新层,并在“中将发布配置与发布配置一起发布应用程序/发布” 目录。
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Orders.dll"]
最后一层使用“基础” (我们的轻量级运行时映像)。将文件从发布层的 / app / publish 位置复制到设置的工作目录,然后设置应用程序的入口点。
因此,我们正在使用2张单独的图像。 SDK 生成我们的应用程序,并 aspnet 图像将我们的应用程序托管在容器中,但要注意的重要一点是,将要生成的最终容器将仅包含aspnet运行时,并且尺寸较小。
所有这些东西都已记录在案,可以进行搜索,但是我苦苦挣扎,因为信息分散了。希望它将为将来对ASP.Net Core和Docker陌生的任何人节省一些时间。