在Linux和Windows的Docker容器中运行ASP.NET Core

译者序:其实过去这周我都在研究这方面的内容,结果周末有事没有来得及总结为文章,Scott Hanselman就捷足先登了。那么我就来翻译一下这篇文章,让更多的中文读者看到。当然Scott遇到的坑我也遇到了。

不过首先,对于不熟悉的朋友我还是来解释一下Linux容器和Windows容器的概念。

由于容器成为虚拟化和应用托管的一种不可避免的选项,Windows也开始为公众提供容器功能(其实微软具备和使用容器技术很久了)。这样的容器功能在内部的引擎通过两种方式来实现,内核级别(仅Windows Server 2016支持)和Hyper-v级别(Windows 10和Windows Server 2016支持)。但是对外的接口和标准又遵循Docker的,这样的好处是Windows容器生态可以和现有的Linux容器生态很好的结合。所以Windows容器称之为Docker on Windows。Windows容器的出现为传统的Windows服务端应用程序的容器化开启了新天地,比如把Qlik Sense的服务器放到容器中来即时编排集群。

而之前Docker公司也针对Windows 10推出过利用Hyper-V来跑一个Linux虚拟机作为容器宿主主机的发行版本。那个称之为Docker for Windows。

所以在Windows 10上,你可以同时安装Docker for Windows和Docker on Windows,只是不能同时运行两者。两者默认的安装目录不同,但是客户端(即Docker.exe)是同名的,所以我把on版本的客户端执行文件改了个名字就可以两个一起用了。其实客户端虽然版本不同,但是基本的命令还是都是兼容的,用其中一个就够了。因为Docker Deamon在两者中都是同样的访问地址。

Scott Hanselman的文章地址为:http://www.hanselman.com/blog/ExploringASPNETCoreWithDockerInBothLinuxAndWindowsContainers.aspx

=====我是译文正文开始的分隔符=====

在去年5月的时候,使用ASP.NET和Docker来折腾一些事情还步履蹒跚。不过,伟大之处就是我们一直在进步。我曾经就写过一篇博客文章来展示如何把ASP.NET 5(当时还称之为5呢,现在已经改名为Core 1.0了)应用发布到Docker中。后来,在2015年11月,类似Docker Toolbox和Kitematic这样的新工具让事情变得更加容易。在2016年5月Docker for Windows Beta继续让这件事情易如反掌。

那么来到2016年10月这个时候,我们来看看如何使用ASP.NET Core、Docker和Windows来进行开发。

我安装了如下东西:

Docker for Windows真的非常好,它可以自动为你配置好Hyper-V,创建一个Docker宿主OS,并启动好这个虚拟机。节约了大量的时间。

这是我的Linux宿主,我无需太多关心它的情况。我将会通过命令行或Visual Studio来完成所有事情。

首先通过File | New Project来创建一个运行在.NET Core中的ASP.NET Core应用程序。

接着在项目名称上点击右键并选择Add | Docker Support。这一菜单来自Visual Studio Tools for Docker扩展。这个步骤会添加基本的Dockerfile和其他docker-compose文件。通过这样的开箱即用的步骤,我就完成了所有的配置从而能够把ASP.NET Core应用程序部署到Docker Linux容器中。

ASP.NET Core运行在Docker Linux容器中

从我这个ASP.NET Core应用当中,我们可以看到其使用的基础镜像(就是Dockerfile中的FROM语句)是Linux的ASP.NET Core镜像。

FROM microsoft/aspnetcore:1.0.1
ENTRYPOINT ["dotnet", "WebApplication4.dll"]
ARG source=.
WORKDIR /app
EXPOSE 80
COPY $source .

接下来,由于我不希望Docker编译我的应用程序,只想发布到本地。可以阅读Steve Laske的博客文章"Building Optimized Docker Images with ASP.NET Core"来了解如何在一个容器中构建应用程序而在其他容器中运行。这样做优化了服务器的使用率和资源。

我将通过如下命令行指令来发布、构建镜像并运行它。

>dotnet publish

>docker build bin\Debug\netcoreapp1.0\publish -t aspnetcoreonlinux 

>docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
aspnetcoreonlinux latest dab2bff7e4a6 28 seconds ago 276.2 MB
microsoft/aspnetcore 1.0.1 2e781d03cb22 44 hours ago 266.7 MB >docker run -it -d -p 85:80 aspnetcoreonlinux
1cfcc8e8e7d4e6257995f8b64505ce25ae80e05fe1962d4312b2e2fe33420413 >docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1cfcc8e8e7d4 aspnetcoreonlinux "dotnet WebApplicatio" 2 seconds ago Up 1 seconds 0.0.0.0:85->80/tcp clever_archimedes

到此,我的ASP.NET Core应用就可以运行在Docker中了。我们现在已经尝试了一个Docker容器,它是托管在Windows中通过Hyper-V来运行的Linux宿主中。

我们还可以做点别的什么呢?

ASP.NET Core运行在一个运行着Windows Nano Server的Docker Windows容器中

有这样一种Windows Server,称之为Windows Server Core,它删除了UI相关的东西;有这样一种Windows Server,称之为Windows Nano Server,它让Windows缩减到只有几百M而不是几G。这意味着从所需功能和服务器使用率的角度看,这是一个非常好的选择,让你部署的空间占用尽可能的小。

让我来看一下我是否能把ASP.NET Core通过Kestrel【译者注:ASP.NET Core的跨平台Web服务器实现】运行到Windows Nano Server中。当然,由于Nano功能强大,我也能在这个容器中运行IIS,这里有文档说明

来自Docker公司的Michael Friis有一篇很棒的博客文章描述了在Windows Server容器中构建和运行Docker应用。在安装了最新版的Docker for Windows之后,你就可以通过上下文菜单来在Linux和Windows容器间切换。

那么现在我就来用用Windows容器的Docker。你可能还不知道你已经拥有Windows容器了!它已经和Windows 10周年更版本一起发布了。你可以在Windows特性对话框中启用容器功能:

我将修改一下Dockerfile来使用Windows Nano Server镜像。我也可以在Docker内部通过环境变量和Expose命令来控制ASP.NET暴露的端口。

FROM microsoft/dotnet:nanoserver
ENTRYPOINT ["dotnet", "WebApplication4.dll"]
ARG source=.
WORKDIR /app
ENV ASPNETCORE_URLS http://+:82
EXPOSE 82
COPY $source .

接着,我发布并构建……

>dotnet publish
>docker build bin\Debug\netcoreapp1.0\publish -t aspnetcoreonnano

然后,运行它,映射Windows外部端口到Windows容器内部!

注意:在Windows 10通过“NAT”(网络地址转换)来和容器通讯的时候,有一个Bug,你不能如你(我)所愿的那样,直接通过 http://localhost:82 来访问容器应用。你不得不通过容器本身的IP来访问。一旦听到这个Bug的更多消息和被修复的情况,我会及时公布在这里。它应该会通过Windows Update在几天内出现。从Docker得到容器的IP地址的方法为:docker inspect -f "{{ .NetworkSettings.Networks.nat.IPAddress }}" HASH

那么,我将通过如下命令在Windows Nano Server中运行我的ASP.NET Core应用(再次说明一下,它将运行在Windows 10的Nano Server容器内)。

>docker run -it -d -p 88:82 aspnetcoreonnano
afafdbead8b04205841a81d974545f033dcc9ba7f761ff7e6cc0ec8f3ecce215 >docker inspect -f "{{ .NetworkSettings.Networks.nat.IPAddress }}" afa
172.16.240.197

现在,我可以通过172.16.240.197:82来访问这个站点。一旦上面的Bug被修复后,我们就能像其他容器那样访问它了。

Windows容器的最美好的一面就是它非常快和轻量级。一旦镜像被下载下来,在机器上构建好,那么你通过Docker来启动和停止它们都是秒完成。

不过,你也可以通过如下命令来使用Docker隔离Windows容器:

docker run --isolation=hyperv -it -d -p 86:82 aspnetcoreonnano

如此一来,实例完全是通过Hyper-v本身来隔离运行的。你可以获得世界上最好的东西:速度、方便的部署加上可选且便捷的隔离。

ASP.NET Core运行在一个运行着Windows Server Core的Docker Windows容器中

接下来,我把Dockerfile修改为使用完整的Windows Server Core镜像。在下载安装这个镜像后,其占用大约8G的空间,需要花一点时间来下载和解压,不过它确实是真正的Windows。你也可以选择运行为一个容器或者隔离的Hyper-V容器。

这里,我通过修改FROM语句来使用包含了.NET Core的Windows Sever Core:

FROM microsoft/dotnet:1.0.0-preview2-windowsservercore-sdk
ENTRYPOINT ["dotnet", "WebApplication4.dll"]
ARG source=.
WORKDIR /app
ENV ASPNETCORE_URLS http://+:82
EXPOSE 82
COPY $source .

注意:我听说使用Windows Sever Core的.NET Core镜像有可能会取消。因为让.NET Core运行在Windows Nano Server或其他轻量级镜像中更有意义。你应该把Sever Core用于那些更加笨重的应用。如果你真的需要运行在Sever Core的.NET Core,你可以制作自己的Dockerfile来轻易构建你所要的镜像。

接下来,我将再次发布、构建和运行。

>docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
aspnetcoreonnano latest 7e02d6800acf 24 minutes ago 1.113 GB
aspnetcoreonservercore latest a11d9a9ba0c2 28 minutes ago 7.751 GB

由于容器能够非常快的启动和停止,所以我可以利用跑在容器中的Redis、一个SQL容器和包含其他部分的第三个容器来跑一个完整的Web集群。或者混合并配对。

>docker ps
CONTAINER ID IMAGE COMMAND PORTS NAMES
d32a981ceabb aspnetcoreonwindows "dotnet WebApplicatio" 0.0.0.0:87->82/tcp compassionate_blackwell
a179a48ca9f6 aspnetcoreonnano "dotnet WebApplicatio" 0.0.0.0:86->82/tcp determined_stallman
170a8afa1b8b aspnetcoreonnano "dotnet WebApplicatio" 0.0.0.0:89->82/tcp agitated_northcutt
afafdbead8b0 aspnetcoreonnano "dotnet WebApplicatio" 0.0.0.0:88->82/tcp naughty_ramanujan
2cf45ea2f008 a7fa77b6f1d4 "dotnet WebApplicatio" 0.0.0.0:97->82/tcp sleepy_hodgkin

总结

再次,让我们阅读Michae的另外一篇文章,他使用Docker Compose来把ASP.NET Music Store示例跑在一个Windows容器中,而SQL Express跑在另外一个中,以及Steve Lasker的博客文章(实际上他的整篇文章都是金矿)中提到的为ASP.NET Core制作一个优化的Docker镜像

IMAGE ID            RESPOSITORY                   TAG                 SIZE
0ec4274c5571 web optimized 276.2 MB
f9f196304c95 web single 583.8 MB
f450043e0a44 microsoft/aspnetcore 1.0.1 266.7 MB
706045865622 microsoft/aspnetcore-build 1.0.1 896.6 MB

Steve提到了大量的技巧,让你可以解决Docker和ASP.NET Core在一起的大部分问题。

所有的一切意味着(IMHO),你可以把ASP.NET Core用在:

  • 在Linux中跑ASP.NET Core

    • 在Docker容器里面
    • 在任何云平台中
  • 在Windows,、Windows Server、Server Core和Nano Server中跑ASP.NET Core
    • 在Docker的Windows容器里面
    • 在Docker的Hyper-V隔离容器里面

这意味着你可以选择任意特性支持和为服务器使用率和便捷度优化过的尺寸大小。一旦所有的工具(Docker for Windows和Visual Studio Docker Tools)准备妥当,我们就能拥有良好的调试环境,和从开发到生产的工作流支持。

你在使用Docker、容器和ASP.NET Core进行开发了吗?希望在评论中看到你们的声音。

Docker容器中运行ASP.NET Core的更多相关文章

  1. 在Linux和Windows的Docker容器中运行ASP.NET Core

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 译者序:其实过去这周我都在研究这方面的内容,结果周末有事没有来得及总结为文章,Scott H ...

  2. Docker----与Asp.net core 的完美结合,在docker容器中创建Asp.Net Core 项目

    在腾讯云上买了一个小容量的服务器,搭建一个docker环境后,可以尝试做一些单系统做起来很麻烦的东西.譬如说,你在windows OS或UbuntuOS中,突然想玩CentOS了,你可以选择将电脑再装 ...

  3. 在docker中运行ASP.NET Core Web API应用程序

    本文是一篇指导快速演练的文章,将介绍在docker中运行一个ASP.NET Core Web API应用程序的基本步骤,在介绍的过程中,也会对docker的使用进行一些简单的描述.对于.NET Cor ...

  4. docker中运行ASP.NET Core Web API

    在docker中运行ASP.NET Core Web API应用程序 本文是一篇指导快速演练的文章,将介绍在docker中运行一个ASP.NET Core Web API应用程序的基本步骤,在介绍的过 ...

  5. .Net Core 3.0 的 docker 容器中运行 无法 访问 Oracle数据库

    .Net  Core 3.0 的 docker 容器中运行 无法 访问 Oracle数据库  , 一直报下面的错误 ORA-00604: error occurred at recursive SQL ...

  6. 丙申年把真假美猴王囚禁在容器中跑 ASP.NET Core 1.0

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  7. Docker容器环境下ASP.NET Core Web API

    Docker容器环境下ASP.NET Core Web API应用程序的调试 本文主要介绍通过Visual Studio 2015 Tools for Docker – Preview插件,在Dock ...

  8. .NetCore下使用IdentityServer4 & JwtBearer认证授权在CentOS Docker容器中运行遇到的坑及填坑

    今天我把WebAPI部署到CentOS Docker容器中运行,发现原有在Windows下允许的JWTBearer配置出现了问题 在Window下我一直使用这个配置,没有问题 services.Add ...

  9. 一个docker容器中运行多个服务还是弄一堆docker容器运行?

    不建议直接在单个 Docker 容器中运行多个程序. 以 2017年 10 月18 日 Docker 官方支持 Kubernetes 为分水岭计算,Kubernetes 赢得容器编排之战的最终胜利已经 ...

随机推荐

  1. Unix网络编程(3)——C/S模型几种情况

    UNP第五章描述了在客户端和服务器连接建立之后会出现的几种情况,并给出了解决方案,做一个简单的总结. 先给出这个简单的回射C/S程序的模型如下图.   1.客户端和服务器正常终止连接 客户端从标准输入 ...

  2. 计算机程序和C++语言简介

    C++程序设计 第一章 计算机程序和C++语言简介 1.计算机是一台能够存储并处理数据的电子设备,包含硬件和软件两部分. 2.计算机硬件由: 1)中央处理单元(Central Processing U ...

  3. java基础学习总结五(递归算法、冒泡排序、查看生成API)

    一:递归算法 概念:自己调用自己的方法 示例代码如下: @Test /** * 递归求和 * 5+4+3+2+1=15 */ public void getSum() { long sum = sum ...

  4. Java中处理Linux信号量

    为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/ShiJiaqi. http://www.cnblogs.com/shijiaqi1066/p/5976361. ...

  5. [引]LINQ to XML 类概述

    本文转自:http://msdn.microsoft.com/zh-cn/library/bb387023.aspx 本主题提供 System.Xml.Linq 命名空间中 LINQ to XML 类 ...

  6. android之TCP客户端框架

    一.程序框架 1.1 创建方法 onCreate 1.1.1 创建连接按键线程,并使能线程(触发原因:可按键.其他操作,并进行状态判断): Connect_Thread connect_Thread ...

  7. golang 依赖控制反转(IoC)

    主流开发语言,为了达到项目间的低耦合,都会借助IoC框架来实现.即抽象和实现分离,使用抽象层,不用关心这些抽象层的具体实现:抽象层的实现,可以独立实现.现在比较流行的领域驱动设计(ddd),为了达到将 ...

  8. 【Objective-C】3 -self关键字

    一.Java中的this只能用在动态方法中,不能用在静态方法中 1.在动态方法中使用this关键字 1 public class Student { 2 private int age; 3 publ ...

  9. jquery animate 制作简单弹幕

    定位滚动条 $("html,body").animate({scrollTop:$(".middle1").offset().top},1000) 弹幕 < ...

  10. redhat6.5 配置使用centos的yum源

    新安装了redhat6.5安装后,登录系统,使用yum update 更新系统.提示: This system is not registered to Red Hat Subscription Ma ...