Update 20160910 HOSTING .NET CORE ON LINUX WITH DOCKER - A NOOB'S GUIDE.md

This commit is contained in:
Lv Feng 2016-10-02 02:52:53 +08:00 committed by GitHub
parent 2c9cd6b7b0
commit 4b494091c9

View File

@ -4,7 +4,7 @@ HOSTING .NET CORE ON LINUX WITH DOCKER - A NOOB'S GUIDE
=====
This post builds on my previous [introduction to .NET Core][1]. First I upgrade that RESTful API from .NET Core RC1 to .NET Core 1.0, then I add support for Docker and describe how to host it on Linux in a production environment.
这篇帖子建立在我之前的帖子【.NET 核心入门】【1】基础之上。首先,我把应用程序界面从 .NET Core RC1 升级到了 .NET Core 1.0,然后,我增加了对 Docker 的支持并描述了如何在 Linux 生产环境里托管它。
这篇帖子建立在我之前的文章【.NET 核心入门】【1】基础之上。首先,我把应用程序界面I】从 .NET Core RC1 升级到了 .NET Core 1.0,然后,我增加了对 Docker 的支持并描述了如何在 Linux 生产环境里托管它。
![](http://blog.scottlogic.com/nsoper/assets/noob.png)
@ -27,7 +27,7 @@ You can jump straight to the finished source code on GitHub.
### 转换到 .NET CORE 1.0
Naturally, my first port of call when thinking about how to upgrade the API from RC1 to 1.0 was to Google it with Bing. There are two pretty comprehensive guides that I followed:
自然地,当我考虑如何把 .NET Core RC1 升级到 .NET Core 1.0 时想到的第一个求助端口就是谷歌搜索。我是按照下面这两条非常全面的指导来进行升级的:
自然地,当我考虑如何把应用程序界面【API】 .NET Core RC1 升级到 .NET Core 1.0 时想到的第一个求助的地方就是谷歌搜索。我是按照下面这两条非常全面的指导来进行升级的:
- [Migrating from DNX to .NET Core CLI][2]
- [Migrating from ASP.NET 5 RC1 to ASP.NET Core 1.0][3]
@ -55,26 +55,37 @@ Unfortunately, there will be plenty of third party developers that will be playi
不幸的是,将有大量的第三方开发者扮演追赶 .NET Core 1.0 的角色,我非常同情他们,因为他们通常在休息时间还坚持工作但却依旧根本无法接近微软的可用资源。我建议阅读 Travis Illig 的文章【.NET Core 1.0 发布了,但 Autofac 在哪儿】【4】?这是一篇关于第三方开发者观点的文章。
Having made these changes I was able to dotnet restore, dotnet build and dotnet run from the project.json directory and see the API working as before.
做了这些改变以后,我可以从 project.json 目录恢复、构建并运行 dotnet可以看到应用程序界面【】又像以前一样工作了。
### RUNNING WITH DOCKER
### 通过 DOCKER 运行
At the time of writing, Docker only really works on Linux. There is beta support for Docker on Windows and OS X but they both rely on virtualisation so Ive chosen to run Ubuntu 14.04 as a VirtualBox. Follow these instructions if you havent already got Docker installed.
在我写这篇文章的时候, Docker 只能够在 Linux 系统上工作。在 Windows 系统和 OS X 上有 beta 支持 Docker但是它们都必须依赖于虚拟化技术因此我选择把 Ubuntu 14.04 当作虚拟机来运行。如果你还没有安装过 Docker请按照指导来安装。
Ive been doing a bit of reading about Docker recently but Ive never tried to actually do anything with it until now. Ill assume the reader has no Docker knowledge so Ill explain all parts of the commands that Im using.
我最近阅读了一些关于 Docker 的东西,但我直到现在还没有真正用它来干任何事。我假设读者还没有关于 Docker 的知识,因此我会解释我所使用的所有命令。
#### HELLO DOCKER
#### HELLO DOCKER
Having installed Docker on my Ubuntu machine, my next move was to follow the instructions at https://www.microsoft.com/net/core#docker to see how to get started with .NET Core and Docker.
在 Ubuntu 上安装好 Docker 之后,我所进行的下一步就是按照 https://www.microsoft.com/net/core#docke 上的介绍来开始运行 .NET 核心和 Docker.
First start a container with .NET Core installed:
首先开始一个配有已安装的 .NET Core 的 container。
```
docker run -it microsoft/dotnet:latest
```
The -it option means interactive so having executed this command you will be inside the container and free to run any bash commands you like.
-it 选项意味着你可以在 container 内交互执行这条命令并按照你所希望的那样自由执行任何 bash 命令。
Then we can run five commands to get Microsofts Hello World .NET Core console application running inside Docker!
然后我们可以运行下面这五条命令个来获得在 Docker 内部运行的 Microsofts Hello World .NET 核心控制台运用程序。
1. mkdir hwapp
2. cd hwapp
@ -83,18 +94,24 @@ Then we can run five commands to get Microsofts Hello World .NET Core console
5. dotnet run
You can exit to leave the container, then docker ps -a to show that you have created a container which has exited. You should really now tidy up that container using docker rm <container_name>.
你可以通过退出来离开 container然后在 Docker 内运行 ps -a 命令会显示你已经创建了一个已退出的 container。你可以通过在 Docker 上运行命令 rm <container_name>. 来整理一下容器。
#### MOUNTING THE SOURCE
#### 安装源代码
My next move was to use the same microsoft/dotnet image as above but to mount the source for my application as a data volume.
我的下一步骤是使用和上面相同的 microsoft/dotnet 图像,但是将我的应用程序的源代码作为数据卷
First check out the repository at the relevant commit:
首先检查有相关提交的仓库:
1. git clone https://github.com/niksoper/aspnet5-books.git
2. cd aspnet5-books/src/MvcLibrary
3. git checkout dotnet-core-1.0
Now start a container running .NET Core 1.0 with the source located at /books. Note that youll need to change the /path/to/repo part to match your machine:
现在开启一个 container 来运行位于 /book 目录下伴有源程序的 .NET Core 1.0。 注意更改 /path/to/repo 这部分文件来匹配你的电脑:
```
docker run -it \
@ -103,6 +120,7 @@ microsoft/dotnet:latest
```
Now you can run the application inside the container!
现在你可以运行 container 中的应用程序了!
```
cd /books
@ -111,12 +129,18 @@ dotnet run
```
Thats great as a proof of concept but we dont really want to have to worry about mounting the source code into a container like this whenever we want to start the application.
作为一个概念的证明,这的确很棒,但是我们不想无论何时打算运行一个程序都要考虑如何把源代码安装到 container 里。
#### ADDING A DOCKERFILE
#### 增加一个 DOCKERFILE
The next step I took was to introduce a Dockerfile, which will allow the application to be started easily inside its own container.
我的下一步骤是引入一个 Docker 文件,这将允许应用程序很容易在自己的 container 内启动。
My Dockerfile lives in the src/MvcLibrary directory alongside project.json and looks like this:
我的 Docker 文件和 project.json 一样位于 src/MvcLibrary 目录下,看起来像下面这样:
```
FROM microsoft/dotnet:latest
@ -135,45 +159,64 @@ CMD [ "dotnet", "run" ]
```
Strictly, the `RUN mkdir -p /usr/src/books` command is not needed because COPY will create any missing directories automatically.
严格来说RUN mkdir -p /usr/src/books 命令是不需要的,因为 COPY 会自动为丢失的目录创建副本。
Docker images are built in layers. We start from the image containing .NET Core and add another layer which builds the application from source then runs the application.
Docker 图像是建立在图层里面的,我们从包含 .NET Core 的图像开始,添加另一个从源生成应用程序的层,然后运行这个运用程序。
Having added the Dockerfile, I then ran the following commands to build the image and start a container using that image (make sure you are in the same directory as the Dockerfile and you should really use your own username):
添加了 Docker 文件以后,我通过运行下面的命令来生成一个图像并使用生成的图像打开一个 container确保在和 Docker 文件相同的目录下进行操作并且你应该使用自己的用户名)。
1. docker build -t niksoper/netcore-books .
2. docker run -it niksoper/netcore-books
You should see that the application started listening just as before, except this time we dont need to bother mounting the source code because its already contained in the docker image.
你应该看到程序能够和之前一样的运行,不过这一次我们不需要像之前那样安装源代码,因为源代码已经包含在 docker 图像里面了。
#### EXPOSING AND PUBLISHING A PORT
#### 暴露并发布端口
This API isnt going to be very useful unless we can communicate with it from outside the container. Docker has the concept of exposing and publishing ports, which are two very different things.
这个应用程序界面【API】用处不大除非我们可以从 container 外面和它进行通信。 Docker 已经有了暴露和发布端口的概念,但这是两件完全不同的事。
From the official Docker documentation:
通过 Docker 官方文件:
>The EXPOSE instruction informs Docker that the container listens on the specified network ports at runtime. EXPOSE does not make the ports of the container accessible to the host. To do that, you must use either the -p flag to publish a range of ports or the -P flag to publish all of the exposed ports.
> EXPOSE 指令通知 Docker 上的 container 监听正在运行的特殊网络端口。EXPOSE 指令不能够让 container 访问主机。要使 container 能够访问主机,你必须通过 -p 标志来发布一系列端口或者使用 -P 标志来发布所有暴露的端口
EXPOSE only adds metadata to the image so you can think of it as documentation for the consumers of the image. Technically, I could have left out the EXPOSE 5000 line completely because I know the port that the API is listening on but leaving it in is helpful and certainly recommended.
EXPOSE 指令只会将元数据添加到图像上,所以你可以认为它是图像消费者的文件。从技术上讲,我本应该忽略 5000 行 EXPOSE 指令因为我知道应用程序界面【API】正在监听的端口但把它们留下很有用并且是值得推荐的。
At this stage I want to access the API directly from the host so I need to use -p to publish the port - this allows a request to port 5000 on the host be forwarded to port 5000 in the container regardless of whether the port has previously been exposed via the Dockerfile:
在这个阶段我想直接从主机访问应用程序界面【API】因此我需要通过 -p 命令来发布端口,这将允许请求从主机上的端口 5000 转发到 container 上的端口 5000无论这个端口是不是之前通过 Docker 文件暴露的。
```
docker run -d -p 5000:5000 niksoper/netcore-books
```
Using -d tells docker to run the container in detached mode so we wont see its output but it will still be running and listening on port 5000 - prove this to yourself with docker ps.
通过 -d 指令告诉 docker 在分离模式下运行 container因此我们不能看到它的输出但是它依旧会运行和监听端口 5000。你可以通过 docker ps 来证实这件事。
So then I prepared to celebrate by making a request from the host to the container:
因此,接下来我准备庆祝成功把一个请求从主机转发到了 container 里:
```
curl http://localhost:5000/api/books
```
It didnt work.
它不能够工作。
Making the same curl request repeatedly, I see one of two errors - either curl: (56) Recv failure: Connection reset by peer or curl: (52) Empty reply from server.
重复进行相同请求我看到了一两个错误56接收失败连接同等或卷曲复位52来自服务器的空回复。
I went back to the docker run documentation and double checked I was using the -p option correctly as well as EXPOSE in the Dockerfile. I couldnt see the problem and became a bit sad…
After pulling myself together, I decided to consult one of my local DevOps heroes - Dave Wybourn (also mentioned in this post on Docker Swarm). His team had run into this exact problem and the issue was the way that I had (not) configured Kestrel - the new lightweight, cross platform web server used for .NET Core.