了解如何在我们的开发环境中使用Docker和JetBrains Rider。

在本教程的这一点上,您可能正在围绕集装箱化、它是什么以及它是否适合您来阐述想法和想法。本节将开始在几种类型的.NET应用程序中使用Docker,并了解普通.NET开发人员的体验。
在接下来的教程中,我们将使用JetBrains Rider和.NET5 SDK。我们还需要安装Docker Desktop来运行我们的容器。

Docker Hello, World

如果没有“Hello,World”应用程序,什么教程才算完整?从JetBrains Rider的新解决方案对话框开始,我们可以从模板中选择控制台应用程序。在右侧的配置窗口中,我们需要从Docker支持选项中选择Linux选项。
image.png
一旦创建并加载了我们的解决方案,我们将在新的控制台项目中看到三个文件:Program.csDockerfile.dockerIgnore。在查看Dockerfile之前,让我们先更改控制台应用程序的输出。

  1. using System;
  2. Console.WriteLine("Hello Docker!");

现在,让我们打开Dockerfile,逐行查看发生了什么。.NET5模板附带的默认Docker定义做了一些Docker生态系统中熟悉的事情。它使用两个镜像来创建最终镜像。我们的应用程序的最终镜像将小得多,因为它将只使用.NET运行时,而不是整个SDK。

  1. FROM mcr.microsoft.com/dotnet/runtime:5.0 AS base
  2. WORKDIR /app
  3. FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
  4. WORKDIR /src
  5. COPY ["HelloDocker/HelloDocker.csproj", "HelloDocker/"]
  6. RUN dotnet restore "HelloDocker/HelloDocker.csproj"
  7. COPY . .
  8. WORKDIR "/src/HelloDocker"
  9. RUN dotnet build "HelloDocker.csproj" -c Release -o /app/build
  10. FROM build AS publish
  11. RUN dotnet publish "HelloDocker.csproj" -c Release -o /app/publish
  12. FROM base AS final
  13. WORKDIR /app
  14. COPY --from=publish /app/publish .
  15. ENTRYPOINT ["dotnet", "HelloDocker.dll"]

Dockerfile的第一行表示我们的父映像。在本例中,我们使用.NET5的dotnet/runtime映像。Docker定义文件中的第二行设置了/app的工作目录。在本例中,我们为应用程序的最终构建创建目标文件夹。

  1. FROM mcr.microsoft.com/dotnet/runtime:5.0 AS base
  2. WORKDIR /app

以下部分执行几个操作,包括使用dotnet/sdk的不同基本映像、创建一个src目录、复制项目文件和我们项目的源代码,然后将我们的项目构建到/app/build的最终输出目录中。

  1. FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
  2. WORKDIR /src
  3. COPY ["HelloDocker/HelloDocker.csproj", "HelloDocker/"]
  4. RUN dotnet restore "HelloDocker/HelloDocker.csproj"
  5. COPY . .
  6. WORKDIR "/src/HelloDocker"
  7. RUN dotnet build "HelloDocker.csproj" -c Release -o /app/build

请注意as关键字的用法。我们为构建步骤提供中间映像名称,以便我们可以在整个集装箱化过程中引用它们。接下来的几行将使用我们之前的构建映像来发布我们的项目(假设它成功构建)。

  1. FROM build AS publish
  2. RUN dotnet publish "HelloDocker.csproj" -c Release -o /app/publish

最后一部分将重用我们的基本映像,并将构建和发布步骤复制到/app目录中。它还将为我们的容器设置入口点,该容器将运行我们的.NET应用程序。

  1. FROM base AS final
  2. WORKDIR /app
  3. COPY --from=publish /app/publish .
  4. ENTRYPOINT ["dotnet", "HelloDocker.dll"]

太棒了!现在,让我们在容器内运行此应用程序。我们将通过两种方式:Docker CLI和使用JetBrains Rider的Docker集成。
浏览完Dockerfile之后,Docker的新手可能会问一个常见的问题:

Why is the Dockerfiledefinition running dotnet restore with just the project file, and only later is it running dotnet build?

原因在于Docker存储镜像的方式。Dockerfile中的每一步都是一个单独的只读层,Docker引擎只有在有变化时才会替换层。更新代码通常比添加或更新包引用更重要,将两者分开可以确保仅在该层发生更改时才执行完整的包恢复。通过对层的管理,Docker可以重用并加快镜像构建。

Docker CLI

我们需要在解决方案的根目录打开一个终端窗口,在那里我们将运行以下命令将Dockerfile构建到一个映像中。在我们的示例中,我们的项目名称是HelloDocker,但是根据您的项目名称调整命令。我们还有一些可选的构建标志,如--rm-t,前者清除任何中间映像,后者将为我们的新映像命名为hello-docker,帮助我们轻松找到它。
Docker在成功构建之后很长一段时间内都会将映像保存在我们的机器上。持久性提高了未来的构建性能,但以磁盘空间为代价。--rm标志在短期实验中很有用,因为我们可能要探索不同的构建配置。

  1. docker build -f HelloDocker/Dockerfile -t hello-docker --rm .

那个.最后告诉Docker CLI应该将什么上下文上传到我们的容器镜像。如果我们忘记添加路径,我们的Docker映像构建将失败,因为Docker将找不到我们的项目文件。
运行该命令,我们将在终端中看到以下输出。

  1. docker build -f HelloDocker/Dockerfile -t hello-docker --rm .
  2. [+] Building 4.7s (18/18) FINISHED
  3. > [internal] load build definition from Dockerfile 0.0s
  4. > => transferring dockerfile: 37B 0.0s
  5. > [internal] load .dockerignore 0.0s
  6. > => transferring context: 2B 0.0s
  7. > [internal] load metadata for mcr.microsoft.com/dotnet/sdk:5.0 0.0s
  8. > [internal] load metadata for mcr.microsoft.com/dotnet/runtime:5.0 0.0s
  9. > [build 1/7] FROM mcr.microsoft.com/dotnet/sdk:5.0 0.0s
  10. > [internal] load build context 0.0s
  11. > => transferring context: 6.61kB 0.0s
  12. > [base 1/2] FROM mcr.microsoft.com/dotnet/runtime:5.0 0.0s
  13. > CACHED [build 2/7] WORKDIR /src 0.0s
  14. > CACHED [build 3/7] COPY [HelloDocker/HelloDocker.csproj, HelloDocker/] 0.0s
  15. > CACHED [build 4/7] RUN dotnet restore "HelloDocker/HelloDocker.csproj" 0.0s
  16. > [build 5/7] COPY . . 0.0s
  17. > [build 6/7] WORKDIR /src/HelloDocker 0.0s
  18. > [build 7/7] RUN dotnet build "HelloDocker.csproj" -c Release -o /app/build 2.7s
  19. > [publish 1/1] RUN dotnet publish "HelloDocker.csproj" -c Release -o /app/publish 1.8s
  20. > CACHED [base 2/2] WORKDIR /app 0.0s
  21. > CACHED [final 1/2] WORKDIR /app 0.0s
  22. > CACHED [final 2/2] COPY --from=publish /app/publish . 0.0s
  23. > exporting to image 0.0s
  24. > => exporting layers 0.0s
  25. > => writing image sha256:b8ff862ff829ece58c3ac884c5bdc895795347caeefd12e759... 0.0s
  26. > => naming to docker.io/library/hello-docker

现在,让我们使用Docker CLI命令run在新的容器中运行我们的映像。

  1. docker run hello-docker

运行该命令将为我们提供第一个运行Docker托管的应用程序的输出。

  1. docker run hello-docker
  2. Hello Docker!

JetBrains Rider Docker Integration

祝贺你,我们成功了!现在,让我们看看使用JetBrains Rider构建和运行Docker容器的更简单的方法。
JetBrains Rider与Docker集成捆绑在一起,为喜欢GUI体验的开发人员提供了定义、构建和部署映像所需的所有工具。当Dockerfile在我们的编辑器中时,我们将在文件的左上角看到两个绿色的V形。
image.png
让我们设置一些在CLI体验期间使用的命令行标志。我们需要单击V形图标并选择Edit HelloDocker/Dockerfile选项。
image.png
Edit run Configuration对话框中,我们将Image tag设置为hello-docker,并为这个简单的示例添加--rm的构建选项。如果我们没有看到构建选项,我们可以单击Modify Options并启用文本框。
image.png
一旦我们应用了更改,就可以使用chevrons从对话框或编辑器窗口运行它们。我们将在 Services 窗口中看到我们的图像和容器。
image.png
在本教程的后续部分中,我们将详细介绍 Services 窗口。
我们拿到了!我们已经使用Docker CLI和JetBrains Rider的docker集成从Dockerfile定义创建了一个图像。开发人员应该熟悉CLI,但是单击几个按钮的便利性是无与伦比的。