为 ASP.NET Core 应用程序添加 Docker 支持
参考资料
微软提供的 Docker Image
微软为 ASP.NET Core 开发人员提供了三种官方 Docker Image:
- Development: 快速迭代和调试更改,以大尺寸的 Image 换取开发的便利
 - Build: 包含所有用于生成应用的依赖和库,如编译器和其他优化编码的工具,开发人员使用该 Image 创建最终要放置在 Production 环境下的 Image 所需的资产,该 Image 主要用于持续集成。这样的好处在于使得生成工具仅仅需要知道如何运行该 Image,而不用关心其他细节。
 - Production: 用于生产环境运行的 Image,体积经过了优化,因而在多 Host 部署时节省了网络通信时间,所有位于该 Image 中的内容都是为最优化运行应用程序而准备的。
 
Docker Image 命名规则
microsoft/dotnet:<version>-sdk: 该 Image 包含了 .NET Core SDK,其中包含 .NET Core 和 CLI,该 Image 用于支持上述Development和Build使用场景。另外,microsoft/dotnet:sdk表示获取最新版本的 Image。microsoft/dotnet:<versuib>-runtime: 该 Image 包含 .NET Core(运行时和类库)并对运行 .NET Core 应用程序做了优化,对应于上述Production的使用场景。
其他 Image
除了上述三种 Image 之外,微软还提供了一些用于特殊用途的 Image,如
microsoft/dotnet:<version>-runtime-deps:runtime-deps包含了 .NET Core 依赖的操作系统本地库,这种 Image 主要用于 Self-Contained 应用程序。- 各个 Image 的最新版本:
microsoft/dotnet或microsoft/dotnet:latest: SDK Image 的别名microsoft/dotnet:sdkmicrosoft/dotnet:runtimemicrosoft/dotnet:runtime-deps
 
开始第一个 ASP.NET Core Docker App
准备工作
- 安装 .NET Core SDK 2.0
 - 安装一个喜欢的代码编辑器,例如 Visual Studio(Code)。
 - 安装 Docker CE for Windows
 - 安装 Git
 
获取示例项目
首先选取一个工作目录,然后执行:
1  | $ git clone https://github.com/dotnet/dotnet-docker-samples/  | 
克隆完成后,进入 aspnetapp 目录,执行 dotnet run,在容器化应用程序之前,首先确保该应用程序能够运行。
1  | $ cd aspnetapp  | 
确认 dotnet run 正常后,改用 docker 生成并运行:
1  | cd aspnetapp  | 
Docker 的端口映射为
host:container
现在访问 http://{your-host-ip-address}:5000 便可得到示例应用程序的页面。
Visual Studio Docker 工具集
为应用程序添加 Docker 支持
要使 ASP.NET 与 Docker 集成,该项目必须是 .NET Core 项目,Linux 和 Windows 两种类别的容器都支持。ASP.NET Core 项目的 Container 类型必须与本机 Docker 引擎运行的 Container 类型相同。可通过在任务栏图标上右键单击 Docker 图标 -> Switch to Windows containers 或 Switch to Linux containers 功能来进行切换。
创建新的应用程序
对于新创建的 ASP.NET Core 项目,勾选 Enable Docker Support,并选择一个 Docker Container 类型:
为现有项目添加 Docker 支持
Visual Studio 仅支持为 .NET Core 项目添加 Docker 支持,有两种方式,首先打开一个项目
- 选择 Project 菜单 -> Docker Support
 - 右键单击项目 -> 添加 -> Docker Support
 
Visual Studio Docker 概览
当对一个项目添加 Docker 支持后,VisualStudio 将项解决方案目录添加一个 docker-compose.dcproj 项目,其中包含:
- .dockerignore: 生成 build 时需要忽略的文件和目录匹配字段
 - docker-compose.yml: Docker Compose 的定义文件,定义了一系列 Image 的集合用于 
docker-compose build和docker-compose run。 - docker-compose.override.yml: 一个可选文件,也会被 Docker Compose 读取,包含需要对服务进行重写的配置信息。Visual Studio 执行 
docker-compose -f "docker-compose.yml" -f "docker-compose.override.yml"来合并这些文件 
同时,ASP.NET Core 项目文件夹下自动生成了一个名为 Dockerfile 的文件,该文件起始包含 4 个单独的生成环节,其根据 Docker multi-stage build 定义,内容如下:
1  | FROM microsoft/aspnetcore:2.0 AS base  | 
该 Dockerfile 基于 microsoft/aspnetcore Image,该 Image 包含了所有与 ASP.NET Core 相关的 Nuget 包。查看 docker-compose.yml 文件,其中包含了自建 Image 的名称:
1  | version: '3.4'  | 
在这个例子中,如果应用程序以 Debug 模式运行,aspdotnetcoredocker Image 会生成 aspdotnetcoredocker:dev,以 Release 模式运行时,会生成 aspdotnetcoredocker:latest Image。
Image 的名称通常以 Docker Hub 的用户名作为前缀(此处为 frosthe)。也可以自建 Registry 来承载私有的 Image。
调试
在 Debug 模式下按下 F5,同时查看 Visual Studio 的输出窗口,其步骤如下:
microsoft/aspnetcore: 获取 aspnet core runtime Image。microsoft/aspnetcore-build: 获取编译/发布 Image。ASPNETCORE_ENVIRONMENT: Container 内环境变量设置为Development。- Container 暴露 80 端口了并映射到了主机的动态端口,该动态端口由 Docker 主机决定,可通过 
docker ps来查询。 - 应用程序被复制到了 Container 中
 - 默认浏览器被打开,并通过动态端口将调试器附加到了 Container 中。
 
完成后执行 docker images 可以看到生成好的 aspdotnetcoredocker:dev Image 和 microsoft/aspnetcore Image。
1  | REPOSITORY TAG IMAGE ID CREATED SIZE  | 
执行 docker ps 可以看到正在运行的 container。
1  | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES  | 
编辑并继续
与传统 .NET 程序的调试一样,针对静态文件和 Razor 视图的更改都将实时更新,而无需重新编译,但针对源代码的修改,则需要重新编译并重启 Kestrel 服务器,这都在 Container 中完成。
发布 Docker Image
一旦开发和调试完成,需要首先将配置切换至 Release,然后生成应用程序,Docker 工具集会生成一个新的打上 latest 标签的 Image,最后可将该 Image 上传至私有仓库或 Docker Hub。