Core-.NET-Docker-上托管-新手指南-通过-Linux-在 (core是什么意思)

教程大全 2025-07-15 07:53:43 浏览

这篇文章基于我之前的文章 .NET Core 入门。首先,我把 RESTful API 从 .NET Core RC1 升级到了 .NET Core 1.0,然后,我增加了对 Docker 的支持并描述了如何在 Linux 生产环境里托管它。

我是首次接触 Docker 并且距离成为一名 Linux 高手还有很远的一段路程。因此,这里的很多想法是来自一个新手。

安装

Linux

按照上的介绍在你的电脑上安装 .NET Core 。这将会同时在 Windows 上安装 dotnet 命令行工具以及最新的 Visual Studio 工具。

源代码

你可以直接到 GitHub 上找最到最新完整的源代码。

转换到 .NET CORE 1.0

自然地,当我考虑如何把 API 从 .NET Core RC1 升级到 .NET Core 1.0 时想到的第一个求助的地方就是谷歌搜索。我是按照下面这两条非常全面的指导来进行升级的:

当你迁移代码的时候,我建议仔细阅读这两篇指导,因为我在没有阅读第一篇指导的情况下又尝试浏览第二篇,结果感到非常迷惑和沮丧。

我不想描述细节上的改变因为你可以看 GitHub 上的提交。这儿是我所作改变的总结:

唯一令我真正头疼的事是需要移动 Serilog。我本可以实现自己的文件记录器,但是我删除了文件记录功能,因为我不想为了这次操作在这件事情上花费精力。

不幸的是,将有大量的第三方开发者扮演追赶 .NET Core 1.0 的角色,我非常同情他们,因为他们通常在休息时间还坚持工作但却依旧根本无法接近靠拢微软的可用资源。我建议阅读 Travis Illig 的文章 .NET Core 1.0 发布了,但 Autofac 在哪儿?这是一篇关于第三方开发者观点的文章。

做了这些改变以后,我可以从 project.json 目录恢复、构建并运行 dotnet,可以看到 API 又像以前一样工作了。

通过 Docker 运行

在我写这篇文章的时候, Docker 只能够在 Linux 系统上工作。在 Windows 系统和 OS X 上有 beta 支持 Docker,但是它们都必须依赖于虚拟化技术,因此,我选择把 Ubuntu 14.04 当作虚拟机来运行。如果你还没有安装过 Docker,请按照指导来安装。

我最近阅读了一些关于 Docker 的东西,但我直到现在还没有真正用它来干任何事。我假设读者还没有关于 Docker 的知识,因此我会解释我所使用的所有命令。

HELLO DOCKER

在 Ubuntu 上安装好 Docker 之后,我所进行的下一步就是按照上的介绍来开始运行 .NET Core 和 Docker。

首先启动一个已安装有 .NET Core 的容器。

docker run -it microsoft/dotnet:latest

选项表示交互,所以你执行这条命令之后,你就处于容器之内了,可以如你所希望的那样执行任何 bash 命令。

然后我们可以执行下面这五条命令来在 Docker 内部运行起来微软 .NET Core 控制台应用程序示例。

mkdir hwappcd hwappdotnet newdotnet restoredotnet run

你可以通过运行来离开容器,然后运行 Docker ps -a 命令,这会显示你创建的那个已经退出的容器。你可以通过上运行命令来清除容器。

挂载源代码

我的下一步骤是使用和上面相同的 microsoft/dotnet 镜像,但是将为我们的应用程序以数据卷的方式挂载上源代码。

首先签出有相关提交的仓库:

git cloneASPnet5-books/src/MvcLibrarygit checkout dotnet-core-1.0

现在启动一个容器来运行 .NET Core 1.0,并将源代码放在下。注意更改 /path/to/repo 这部分文件来匹配你的电脑:

docker run -it \-v /path/to/repo/aspnet5-books/src/MvcLibrary:/books \microsoft/dotnet:latest

现在你可以在容器中运行应用程序了!

cd /booksdotnet restoredotnet run

作为一个概念性展示这的确很棒,但是我们可不想每次运行一个程序都要考虑如何把源代码安装到容器里。

增加一个 DOCKERFILE

我的下一步骤是引入一个 Dockerfile,这可以让应用程序很容易在自己的容器内启动。

我的 Dockerfile 和 project.json 一样位于 src/MvcLibrary 目录下,看起来像下面这样:

FROM microsoft/dotnet:latest# 为应用程序源代码创建目录RUN mkdir -p /usr/src/booksWORKDIR /usr/src/books# 复制源代码并恢复依赖关系COPY . /usr/src/booksRUN dotnet restore# 暴露端口并运行应用程序EXPOSE 5000CMD [ "dotnet", "run" ]

严格来说, RUN mkdir -p /usr/src/books 命令是不需要的,因为会自动创建丢失的目录。

Docker 镜像是按层建立的,我们从包含 .NET Core 的镜像开始,添加另一个从源代码生成应用程序,然后运行这个应用程序的层。

添加了 Dockerfile 以后,我通过运行下面的命令来生成一个镜像,并使用生成的镜像启动一个容器(确保在和 Dockerfile 相同的目录下进行操作,并且你应该使用自己的用户名)。

docker build -t niksoper/netcore-books .docker run -it niksoper/netcore-books

你应该看到程序能够和之前一样的运行,不过这一次我们不需要像之前那样安装源代码,因为源代码已经包含在 docker 镜像里面了。

暴露并发布端口

这个 API 并不是特别有用,除非我们需要从容器外面和它进行通信。 Docker 已经有了暴露和发布端口的概念,但这是两件完全不同的事。

据 Docker 官方文档:

指令通知 Docker 容器在运行时监听特定的网络端口。指令不能够让容器的端口可被主机访问。要使可被访问,你必须通过标志来发布一个端口范围或者使用标志来发布所有暴露的端口

指令只是将元数据添加到镜像上,所以你可以如文档中说的认为它是镜像消费者。从技术上讲,我本应该忽略 EXPOSE 5000 这行指令,因为我知道 API 正在监听的端口,但把它们留下很有用的,并且值得推荐。

在这个阶段,我想直接从主机访问这个 API ,因此我需要通过指令来发布这个端口,这将允许请求从主机上的端口 5000 转发到容器上的端口 5000,无论这个端口是不是之前通过 Dockerfile 暴露的。

docker run -d -p 5000:5000 niksoper/netcore-books

通过指令告诉 docker 在分离模式下运行容器,因此我们不能看到它的输出,但是它依旧会运行并监听端口 5000。你可以通过来证实这件事。

因此,接下来我准备从主机向容器发起一个请求来庆祝一下:

curl

它不工作。

重复进行相同请求,我看到了两个错误:要么是curl: (56) Recv failure: Connection reset by peer,要么是curl: (52) Empty reply from server

我返回去看 docker run 的文档,然后再次检查我所使用的选项以及 Dockerfile 中的指令是否正确。我没有发现任何问题,这让我开始有些沮丧。

重新振作起来以后,我决定去咨询当地的一个 Scott Logic DevOps 大师 – Dave Wybourn(也在这篇 Docker Swarm 的文章里提到过),他的团队也曾遇到这个实际问题。这个问题是我没有配置过 Kestral,这是一个全新的轻量级、跨平台 web服务器,用于 .NET Core 。

默认情况下, Kestrel 会监听。但问题是,这儿的是一个回路接口。

据维基百科:

在计算机网络中,localhost 是一个代表本机的主机名。本地主机可以通过网络回路接口访问在主机上运行的网络服务。通过使用回路接口可以绕过任何硬件网络接口。

当运行在容器内时这是一个问题,因为只能够在容器内访问。解决方法是更新Startup.cs里的方法来配置 Kestral 监听的 URL:

public static void Main(string[] args){var host = new WebHostBuilder().UseKestrel().UseContentRoot(Directory.GetCurrentDirectory()).UseUrls("http://*:5000") // 在所有网络接口上监听端口 5000.UseIISIntegration().UseStartup().Build();host.Run();}

通过这些额外的配置,我可以重建镜像,并在容器中运行应用程序,它将能够接收来自主机的请求:

docker build -t niksoper/netcore-books .docker run -d -p 5000:5000 niksoper/netcore-bookscurl -i

我现在得到下面这些相应:

HTTP/1.1 200 OKDate: Tue, 30 Aug 2016 15:25:43 GMTTransfer-Encoding: chunkedContent-Type: application/json; charset=utf-8Server: Kestrel[{"id":"1","title":"RESTful API with ASP.NET Core MVC 1.0","author":"Nick Soper"}]

在产品环境中运行 KESTREL

微软的介绍:

Kestrel 可以很好的处理来自 ASP.NET 的动态内容,然而,网络服务部分的特性没有如 IIS,Apache 或者 Nginx 那样的全特性服务器那么好。反向代理服务器可以让你不用去做像处理静态内容、缓存请求、压缩请求、ssl 端点这样的来自 HTTP 服务器的工作。

因此我需要在我的 Linux 机器上把 Nginx 设置成一个反向代理服务器。微软介绍了如何发布到 Linux 生产环境下的指导教程。我把说明总结在这儿:

这些内容已经超出了本文的范围,因此我将侧重于如何把 Nginx 配置成一个反向代理服务器。自然地,我通过 Docker 来完成这件事。

在另一个容器中运行 NGINX

我的目标是在第二个 Docker 容器中运行 Nginx 并把它配置成我们的应用程序容器的反向代理服务器。

我使用的是来自 Docker Hub 的官方 Nginx 镜像。首先我尝试这样做:

docker run -d -p 8080:80 --name web nginx

这启动了一个运行 Nginx 的容器并把主机上的 8080 端口映射到了容器的 80 端口上。现在在浏览器中打开网址会显示出 Nginx 的默认登录页面。

现在我们证实了运行 Nginx 是多么的简单,我们可以关闭这个容器。

docker rm -f web

把 NGINX 配置成一个反向代理服务器

可以通过像下面这样编辑位于/etc/nginx/conf.d/default.conf配置文件,把 Nginx 配置成一个反向代理服务器:

server {listen 80;location / {proxy_pass}}

通过上面的配置可以让 Nginx 将所有对根目录的访问请求代理到。记住这里的指的是运行 Nginx 的容器。我们可以在 Nginx容器内部利用卷来使用我们自己的配置文件:

docker run -d -p 8080:80 \-v /path/to/my.conf:/etc/nginx/conf.d/default.conf \nginx

注意:这把一个单一文件从主机映射到容器中,而不是一个完整目录。

在容器间进行通信

Docker 允许内部容器通过共享虚拟网络进行通信。默认情况下,所有通过 Docker 守护进程启动的容器都可以访问一种叫做“桥”的虚拟网络。这使得一个容器可以被另一个容器在相同的网络上通过 IP 地址和端口来引用。

你可以通过监测(inspect)容器来找到它的 IP 地址。我将从之前创建的niksoper/netcore-books镜像中启动一个容器并监测(inspect)它:

docker run -d -p 5000:5000 --name books niksoper/netcore-booksdocker inspect books

我们可以看到这个容器的 IP 地址是"IPAddress": "172.17.0.3"

所以现在如果我创建下面的 Nginx 配置文件,并使用这个文件启动一个 Nginx 容器, 它将代理请求到我的 API :

server {listen 80;location / {proxy_pass}}

现在我可以使用这个配置文件启动一个 Nginx 容器(注意我把主机上的 8080 端口映射到了 Nginx 容器上的 80 端口):

docker run -d -p 8080:80 \-v ~/dev/nginx/my.nginx.conf:/etc/nginx/conf.d/default.conf \nginx

一个到的请求将被代理到应用上。注意下面响应的响应头:

DOCKER COMPOSE

在这个地方,我为自己的进步而感到高兴,但我认为一定还有更好的方法来配置 Nginx,可以不需要知道应用程序容器的确切 IP 地址。另一个当地的 Scott Logic DevOps 大师 Jason Ebbin 在这个地方进行了改进,并建议使用 Docker Compose。

概况描述一下,Docker Compose 使得一组通过声明式语法互相连接的容器很容易启动。我不想再细说 Docker Compose 是如何工作的,因为你可以在之前的文章中找到。

我将通过一个我所使用的docker-compose.yml文件来启动:

version: '2'services:books-service:container_name: books-apibuild: .reverse-proxy:container_name: reverse-proxyimage: nginxports:- "9090:8080"volumes:- ./proxy.conf:/etc/nginx/conf.d/default.conf

这是版本 2 语法,所以为了能够正常工作,你至少需要 1.6 版本的 Docker Compose。

这个文件告诉 Docker 创建两个服务:一个是给应用的,另一个是给 Nginx 反向代理服务器的。

BOOKS-SERVICE

这个与docker-compose.yml相同目录下的 Dockerfile 构建的容器叫做。注意这个容器不需要发布任何端口,因为只要能够从反向代理服务器访问它就可以,而不需要从主机操作系统访问它。

REVERSE-PROXY

这将基于 nginx 镜像启动一个叫做reverse-proxy的容器,并将位于当前目录下的proxy.conf文件挂载为配置。它把主机上的 9090 端口映射到容器中的 8080 端口,这将允许我们在上通过主机访问容器。

proxy.conf文件看起来像下面这样:

server {listen 8080;location / {proxy_pass}}

这儿的关键点是我们现在可以通过名字引用books-service,因此我们不需要知道这个容器的 IP 地址!

现在我们可以通过一个运行着的反向代理启动两个容器(意味着这是独立的,因此我们不能看到来自容器的输出):

docker compose up -d

验证我们所创建的容器:

最后来验证我们可以通过反向代理来控制该 API :

curl -i

怎么做到的?

Docker Compose 通过创建一个新的叫做mvclibrary_default的虚拟网络来实现这件事,这个虚拟网络同时用于和reverse-proxy容器(名字是基于docker-compose.yml文件的父目录)。

通过docker network ls来验证网络已经存在:

你可以使用docker network inspect mvclibrary_default来看到新的网络的细节:

注意 Docker 已经给网络分配了子网:"Subnet": "172.18.0.0/16"。部分是无类域内路由选择(CIDR),完整的解释已经超出了本文的范围,但 CIDR 只是表示 IP 地址范围。运行docker network inspect bridge显示子网:"Subnet": "172.17.0.0/16",因此这两个网络是不重叠的。

现在用docker inspect books-api来确认应用程序的容器正在使用该网络:

注意容器的两个别名()是容器标识符(3c42db680459)和由docker-compose.yml给出的服务名(books-service)。我们通过books-service别名在自定义 Nginx 配置文件中来引用应用程序的容器。这本可以通过docker network create手动创建,但是我喜欢用 Docker Compose,因为它可以干净简洁地将容器创建和依存捆绑在一起。

结论

所以现在我可以通过几个简单的步骤在 Linux 系统上用 Nginx 运行应用程序,不需要对主机操作系统做任何长期的改变:

git cloneaspnet5-books/src/MvcLibrarygit checkout blog-dockerdocker-compose up -dcurl -i

我知道我在这篇文章中所写的内容不是一个真正的生产环境就绪的设备,因为我没有写任何有关下面这些的内容,绝大多数下面的这些主题都需要用单独一篇完整的文章来叙述。

对我来说这是一个非常有趣的学习经历,因为有一段时间我对探索 ASP.NET Core 的跨平台支持非常好奇,使用 “Configuratin as Code” 的 Docker Compose 方法来探索一下 DevOps 的世界也是非常愉快并且很有教育意义的。

如果你对 Docker 很好奇,那么我鼓励你来尝试学习它 或许这会让你离开舒适区,不过,有可能你会喜欢它?



如何进入docker的node镜像

1.什么是docker?Docker allows you to package an application with all of its dependencies into a standardized unit for software 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。 容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app)。 几乎没有性能开销,可以很容易地在机器和数据中心中运行。 最重要的是,他们不依赖于任何语言、框架包括系统。 Docker 的目标是实现轻量级的操作系统虚拟化解决方案。 Docker 的基础是 Linux 容器(LXC)等技术。 在 LXC 的基础上 Docker 进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。 用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。 下面的图片比较了 Docker 和传统虚拟化方式的不同之处,可见容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件层面实现。 (图片来自Docker官方网站)简单入门Docker can build images automatically by reading the instructions from a Dockerfile. A Dockerfile is a text document that contains all the commands you would normally execute manually in order to build a Docker image. By calling docker build from your terminal, you can have Docker build your image step by step, executing the instructions 通过读取Dockerfile文件中的指令自动构建镜像。 Dcokerfile是一个文本文件,它包含了构建镜像所需要执行的全部命令。 执行docker build命令,Docker就会按照文档执行并最终创建一个镜像。 (这段话是翻译上面那段话的%>_<%)。 Dockerfile支持支持的语法命令如下:INSTRUCTION argument指令不区分大小写。 但是,命名约定为全部大写。 Dockerfile都必须以FROM命令开始。 FROM命令会指定镜像基于哪个基础镜像创建,接下来的命令也会基于这个基础镜像(译者注:CentOS和Ubuntu有些命令可是不一样的)。 FROM命令可以多次使用,表示会创建多个镜像。 具体语法如下:

windows下安装的docker虚拟机有什么用

下面是安装 Docker 客户端并在上面运行容器的简单步骤。 1. 下载 Boot2Docker在我们开始安装之前,我们需要 Boot2Docker 的可执行文件。 可以从 它的 Github 下载最新版本的 Boot2Docker。 在这篇指南中,我们从网站中下载版本 v1.6.1。 我们从那网页中用我们喜欢的浏览器或者下载管理器下载了名为 的文件。 2. 安装 Boot2Docker现在我们运行安装文件,它会安装 Window Docker 客户端、用于 Windows 的 Git(MSYS-git)、VirtualBox、Boot2Docker Linux ISO 以及 Boot2Docker 管理工具,这些对于开箱即用地运行全功能的 Docker 引擎都至关重要。 3. 运行 Boot2Docker安装完成必要的组件之后,我们从桌面上的“Boot2Docker Start”快捷方式启动 Boot2Docker。 它会要求你输入以后用于验证的 SSH 密钥。 然后会启动一个配置好的用于管理在虚拟机中运行的 Docker 的 unix shell。 为了检查是否正确配置,运行下面的 docker version 命令。 docker version

如何使用Dockerfile构建镜像

docker越来越炙手可热,如果你的团队已经准备开始使用docker,那么私有仓库是必不可少的东西,首先是可以帮助你加快从服务器pull镜像的速度,其次也可以帮助你存放私有的镜像,本文主要为大家介绍如何从公用服务器上讲开放的images备份到本地私有服务器上。dockerimages往往不知不觉就占满了硬盘空间,为了清理冗余的image,可采用以下方法:1.进入root权限sudosu2.停止所有的container,这样才能够删除其中的images:dockerstop$(dockerps-a-q)如果想要删除所有container的话再加一个指令:dockerrm$(dockerps-a-q)3.查看当前有些什么imagesdockerimages4.删除images,通过image的id来指定删除谁dockerrmi想要删除untaggedimages,也就是那些id为的image的话可以用dockerrmi$(dockerimagesgrep^awk{print$3})要删除全部image的话dockerrmi$(dockerimages-q)本篇文章来源于Linux公社网站()原文链接:/Linux/2014-09/

本文版权声明本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请联系本站客服,一经查实,本站将立刻删除。

发表评论

热门推荐