溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Linux怎么通過Docker托管.NET Core

發(fā)布時間:2021-08-13 19:16:50 來源:億速云 閱讀:137 作者:chen 欄目:云計(jì)算

這篇文章主要介紹“Linux怎么通過Docker托管.NET Core”,在日常操作中,相信很多人在Linux怎么通過Docker托管.NET Core問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Linux怎么通過Docker托管.NET Core”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

轉(zhuǎn)換到 .NET CORE 1.0

自然地,當(dāng)我考慮如何把 API 從 .NET Core RC1 升級到 .NET Core 1.0 時想到的第一個求助的地方就是谷歌搜索。我是按照下面這兩條非常全面的指導(dǎo)來進(jìn)行升級的:

  • 從 DNX 遷移到 .NET Core CLI

  • 從 ASP.NET 5 RC1 遷移到 ASP.NET Core 1.0

當(dāng)你遷移代碼的時候,我建議仔細(xì)閱讀這兩篇指導(dǎo),因?yàn)槲以跊]有閱讀第一篇指導(dǎo)的情況下又嘗試瀏覽第二篇,結(jié)果感到非常迷惑和沮喪。

我不想描述細(xì)節(jié)上的改變因?yàn)槟憧梢钥?GitHub 上的提交。這兒是我所作改變的總結(jié):

  • 更新 global.json 和project.json 上的版本號

  • 刪除 project.json上的廢棄章節(jié)

  • 使用輕型 ControllerBase 而不是 Controller, 因?yàn)槲也恍枰c MVC 視圖相關(guān)的方法(這是一個可選的改變)。

  • 從輔助方法中去掉 Http 前綴,比如:HttpNotFound -> NotFound

  • LogVerbose -> LogTrace

  • 名字空間改變: Microsoft.AspNetCore.*

  • 在Startup 中使用SetBasePath(沒有它 appsettings.json 將不會被發(fā)現(xiàn))

  • 通過 WebHostBuilder 來運(yùn)行而不是通過WebApplication.Run 來運(yùn)行

  • 刪除 Serilog(在寫文章的時候,它不支持 .NET Core 1.0)

唯一令我真正頭疼的事是需要移動 Serilog。我本可以實(shí)現(xiàn)自己的文件記錄器,但是我刪除了文件記錄功能,因?yàn)槲也幌霝榱诉@次操作在這件事情上花費(fèi)精力。

不幸的是,將有大量的第三方開發(fā)者扮演追趕 .NET Core 1.0 的角色,我非常同情他們,因?yàn)樗麄兺ǔT谛菹r間還堅(jiān)持工作但卻依舊根本無法接近靠攏微軟的可用資源。我建議閱讀 Travis Illig 的文章 .NET Core 1.0 發(fā)布了,但 Autofac 在哪兒?這是一篇關(guān)于第三方開發(fā)者觀點(diǎn)的文章。

做了這些改變以后,我可以從project.json 目錄恢復(fù)、構(gòu)建并運(yùn)行 dotnet,可以看到 API 又像以前一樣工作了。

通過 Docker 運(yùn)行

在我寫這篇文章的時候, Docker 只能夠在 Linux 系統(tǒng)上工作。在 Windows 系統(tǒng)和 OS X 上有 beta 支持 Docker,但是它們都必須依賴于虛擬化技術(shù),因此,我選擇把 Ubuntu 14.04 當(dāng)作虛擬機(jī)來運(yùn)行。如果你還沒有安裝過 Docker,請按照指導(dǎo)來安裝。

我最近閱讀了一些關(guān)于 Docker 的東西,但我直到現(xiàn)在還沒有真正用它來干任何事。我假設(shè)讀者還沒有關(guān)于 Docker 的知識,因此我會解釋我所使用的所有命令。

HELLO DOCKER

在 Ubuntu 上安裝好 Docker 之后,我所進(jìn)行的下一步就是按照 https://www.microsoft.com/net/core#docker 上的介紹來開始運(yùn)行 .NET Core 和 Docker。

首先啟動一個已安裝有 .NET Core 的容器。

docker run -it microsoft/dotnet:latest

-it 選項(xiàng)表示交互,所以你執(zhí)行這條命令之后,你就處于容器之內(nèi)了,可以如你所希望的那樣執(zhí)行任何 bash 命令。

然后我們可以執(zhí)行下面這五條命令來在 Docker 內(nèi)部運(yùn)行起來微軟 .NET Core 控制臺應(yīng)用程序示例。

mkdir hwapp
cd hwapp
dotnet new
dotnet restore
dotnet run

你可以通過運(yùn)行 exit 來離開容器,然后運(yùn)行 Docker ps -a 命令,這會顯示你創(chuàng)建的那個已經(jīng)退出的容器。你可以通過上運(yùn)行命令 Docker rm <container_name> 來清除容器。

掛載源代碼

我的下一步驟是使用和上面相同的 microsoft/dotnet 鏡像,但是將為我們的應(yīng)用程序以數(shù)據(jù)卷的方式掛載上源代碼。
Linux怎么通過Docker托管.NET Core
首先簽出有相關(guān)提交的倉庫:

git clone https://github.com/niksoper/aspnet5-books.git
cd aspnet5-books/src/MvcLibrary
git checkout dotnet-core-1.0

現(xiàn)在啟動一個容器來運(yùn)行 .NET Core 1.0,并將源代碼放在/book 下。注意更改 /path/to/repo這部分文件來匹配你的電腦:

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

現(xiàn)在你可以在容器中運(yùn)行應(yīng)用程序了!

cd /books
dotnet restore
dotnet run

作為一個概念性展示這的確很棒,但是我們可不想每次運(yùn)行一個程序都要考慮如何把源代碼安裝到容器里。

增加一個 DOCKERFILE

我的下一步驟是引入一個 Dockerfile,這可以讓應(yīng)用程序很容易在自己的容器內(nèi)啟動。

我的 Dockerfile 和 project.json 一樣位于 src/MvcLibrary目錄下,看起來像下面這樣:

FROM microsoft/dotnet:latest

# 為應(yīng)用程序源代碼創(chuàng)建目錄
RUN mkdir -p /usr/src/books
WORKDIR /usr/src/books

# 復(fù)制源代碼并恢復(fù)依賴關(guān)系
COPY . /usr/src/books
RUN dotnet restore

# 暴露端口并運(yùn)行應(yīng)用程序
EXPOSE 5000
CMD [ "dotnet", "run" ]

嚴(yán)格來說,RUN mkdir -p /usr/src/books 命令是不需要的,因?yàn)?COPY 會自動創(chuàng)建丟失的目錄。

Docker 鏡像是按層建立的,我們從包含 .NET Core 的鏡像開始,添加另一個從源代碼生成應(yīng)用程序,然后運(yùn)行這個應(yīng)用程序的層。

添加了 Dockerfile 以后,我通過運(yùn)行下面的命令來生成一個鏡像,并使用生成的鏡像啟動一個容器(確保在和 Dockerfile 相同的目錄下進(jìn)行操作,并且你應(yīng)該使用自己的用戶名)。

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

你應(yīng)該看到程序能夠和之前一樣的運(yùn)行,不過這一次我們不需要像之前那樣安裝源代碼,因?yàn)樵创a已經(jīng)包含在 docker 鏡像里面了。

暴露并發(fā)布端口

這個 API 并不是特別有用,除非我們需要從容器外面和它進(jìn)行通信。 Docker 已經(jīng)有了暴露和發(fā)布端口的概念,但這是兩件完全不同的事。

據(jù) Docker 官方文檔:
EXPOSE指令通知 Docker 容器在運(yùn)行時監(jiān)聽特定的網(wǎng)絡(luò)端口。EXPOSE指令不能夠讓容器的端口可被主機(jī)訪問。要使可被訪問,你必須通過 -p 標(biāo)志來發(fā)布一個端口范圍或者使用 -p 標(biāo)志來發(fā)布所有暴露的端口
EXPOSE 指令只是將元數(shù)據(jù)添加到鏡像上,所以你可以如文檔中說的認(rèn)為它是鏡像消費(fèi)者。從技術(shù)上講,我本應(yīng)該忽略 EXPOSE 5000 這行指令,因?yàn)槲抑?API 正在監(jiān)聽的端口,但把它們留下很有用的,并且值得推薦。

在這個階段,我想直接從主機(jī)訪問這個 API ,因此我需要通過-p 指令來發(fā)布這個端口,這將允許請求從主機(jī)上的端口 5000 轉(zhuǎn)發(fā)到容器上的端口 5000,無論這個端口是不是之前通過 Dockerfile 暴露的。

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

通過 -d 指令告訴 docker 在分離模式下運(yùn)行容器,因此我們不能看到它的輸出,但是它依舊會運(yùn)行并監(jiān)聽端口 5000。你可以通過 docker ps來證實(shí)這件事。

因此,接下來我準(zhǔn)備從主機(jī)向容器發(fā)起一個請求來慶祝一下:

curl http://localhost:5000/api/books

它不工作。

重復(fù)進(jìn)行相同 curl 請求,我看到了兩個錯誤:要么是 curl: (56) Recv failure: Connection reset by peer,要么是 curl: (52) Empty reply from server。

我返回去看 docker run 的文檔,然后再次檢查我所使用的 -p 選項(xiàng)以及 Dockerfile 中的 EXPOSE指令是否正確。我沒有發(fā)現(xiàn)任何問題,這讓我開始有些沮喪。

重新振作起來以后,我決定去咨詢當(dāng)?shù)氐囊粋€ Scott Logic DevOps 大師 - Dave Wybourn(也在這篇 Docker Swarm 的文章里提到過),他的團(tuán)隊(duì)也曾遇到這個實(shí)際問題。這個問題是我沒有配置過 Kestral,這是一個全新的輕量級、跨平臺 web 服務(wù)器,用于 .NET Core 。

默認(rèn)情況下, Kestrel 會監(jiān)聽 http://localhost:5000。但問題是,這兒的localhost是一個回路接口。

據(jù)維基百科:
在計(jì)算機(jī)網(wǎng)絡(luò)中,localhost 是一個代表本機(jī)的主機(jī)名。本地主機(jī)可以通過網(wǎng)絡(luò)回路接口訪問在主機(jī)上運(yùn)行的網(wǎng)絡(luò)服務(wù)。通過使用回路接口可以繞過任何硬件網(wǎng)絡(luò)接口。
當(dāng)運(yùn)行在容器內(nèi)時這是一個問題,因?yàn)?localhost 只能夠在容器內(nèi)訪問。解決方法是更新 Startup.cs里的 Main 方法來配置 Kestral 監(jiān)聽的 URL:

public static void Main(string[] args)
{
  var host = new WebHostBuilder()
    .UseKestrel()
    .UseContentRoot(Directory.GetCurrentDirectory())
    .UseUrls("http://*:5000") // 在所有網(wǎng)絡(luò)接口上監(jiān)聽端口 5000
    .UseIISIntegration()
    .UseStartup<Startup>()
    .Build();

  host.Run();
}

通過這些額外的配置,我可以重建鏡像,并在容器中運(yùn)行應(yīng)用程序,它將能夠接收來自主機(jī)的請求:

docker build -t niksoper/netcore-books .
docker run -d -p 5000:5000 niksoper/netcore-books
curl -i http://localhost:5000/api/books

我現(xiàn)在得到下面這些相應(yīng):

HTTP/1.1 200 OK
Date: Tue, 30 Aug 2016 15:25:43 GMT
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Kestrel

[{"id":"1","title":"RESTful API with ASP.NET Core MVC 1.0","author":"Nick Soper"}]

在產(chǎn)品環(huán)境中運(yùn)行 KESTREL

微軟的介紹:
Kestrel 可以很好的處理來自 ASP.NET 的動態(tài)內(nèi)容,然而,網(wǎng)絡(luò)服務(wù)部分的特性沒有如 IIS,Apache 或者 Nginx 那樣的全特性服務(wù)器那么好。反向代理服務(wù)器可以讓你不用去做像處理靜態(tài)內(nèi)容、緩存請求、壓縮請求、SSL 端點(diǎn)這樣的來自 HTTP 服務(wù)器的工作。
因此我需要在我的 Linux 機(jī)器上把 Nginx 設(shè)置成一個反向代理服務(wù)器。微軟介紹了如何發(fā)布到 Linux 生產(chǎn)環(huán)境下的指導(dǎo)教程。我把說明總結(jié)在這兒:

  1. 通過 dotnet publish 來給應(yīng)用程序產(chǎn)生一個自包含包。

  2. 把已發(fā)布的應(yīng)用程序復(fù)制到服務(wù)器上

  3. 安裝并配置 Nginx(作為反向代理服務(wù)器)

  4. 安裝并配置 supervisor(用于確保 Nginx 服務(wù)器處于運(yùn)行狀態(tài)中)

  5. 安裝并配置 AppArmor(用于限制應(yīng)用的資源使用)

  6. 配置服務(wù)器防火墻

  7. 安全加固 Nginx(從源代碼構(gòu)建和配置 SSL)

這些內(nèi)容已經(jīng)超出了本文的范圍,因此我將側(cè)重于如何把 Nginx 配置成一個反向代理服務(wù)器。自然地,我通過 Docker 來完成這件事。

在另一個容器中運(yùn)行NGINX

我的目標(biāo)是在第二個 Docker 容器中運(yùn)行 Nginx 并把它配置成我們的應(yīng)用程序容器的反向代理服務(wù)器。

我使用的是來自 Docker Hub 的官方 Nginx 鏡像。首先我嘗試這樣做:

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

這啟動了一個運(yùn)行 Nginx 的容器并把主機(jī)上的 8080 端口映射到了容器的 80 端口上。現(xiàn)在在瀏覽器中打開網(wǎng)址 http://localhost:8080 會顯示出 Nginx 的默認(rèn)登錄頁面。

現(xiàn)在我們證實(shí)了運(yùn)行 Nginx 是多么的簡單,我們可以關(guān)閉這個容器。

docker rm -f web

把 NGINX 配置成一個反向代理服務(wù)器

可以通過像下面這樣編輯位于 /etc/nginx/conf.d/default.conf 的配置文件,把 Nginx 配置成一個反向代理服務(wù)器:

server {
  listen 80;

  location / {
    proxy_pass http://localhost:6666;
  }
}

通過上面的配置可以讓 Nginx 將所有對根目錄的訪問請求代理到 http://localhost:6666。記住這里的 localhost 指的是運(yùn)行 Nginx 的容器。我們可以在 Nginx容器內(nèi)部利用卷來使用我們自己的配置文件:

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

注意:這把一個單一文件從主機(jī)映射到容器中,而不是一個完整目錄。

在容器間進(jìn)行通信

Docker 允許內(nèi)部容器通過共享虛擬網(wǎng)絡(luò)進(jìn)行通信。默認(rèn)情況下,所有通過 Docker 守護(hù)進(jìn)程啟動的容器都可以訪問一種叫做“橋”的虛擬網(wǎng)絡(luò)。這使得一個容器可以被另一個容器在相同的網(wǎng)絡(luò)上通過 IP 地址和端口來引用。

你可以通過監(jiān)測inspect容器來找到它的 IP 地址。我將從之前創(chuàng)建的 niksoper/netcore-books 鏡像中啟動一個容器并監(jiān)測inspect它:

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

Linux怎么通過Docker托管.NET Core

我們可以看到這個容器的 IP 地址是 "IPAddress": "172.17.0.3"。

所以現(xiàn)在如果我創(chuàng)建下面的 Nginx 配置文件,并使用這個文件啟動一個 Nginx 容器, 它將代理請求到我的 API :

server {
  listen 80;

  location / {
    proxy_pass http://172.17.0.3:5000;
  }
}

現(xiàn)在我可以使用這個配置文件啟動一個 Nginx 容器(注意我把主機(jī)上的 8080 端口映射到了 Nginx 容器上的 80 端口):

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

一個到http://localhost:8080 的請求將被代理到應(yīng)用上。注意下面 curl 響應(yīng)的 Server 響應(yīng)頭:

Linux通過 Docker 可以托管 .NET Core啦!Linux通過 Docker 可以托管 .NET Core啦!

DOCKER COMPOSE

在這個地方,我為自己的進(jìn)步而感到高興,但我認(rèn)為一定還有更好的方法來配置 Nginx,可以不需要知道應(yīng)用程序容器的確切 IP 地址。另一個當(dāng)?shù)氐?Scott Logic DevOps 大師 Jason Ebbin 在這個地方進(jìn)行了改進(jìn),并建議使用 Docker Compose。

概況描述一下,Docker Compose 使得一組通過聲明式語法互相連接的容器很容易啟動。我不想再細(xì)說 Docker Compose 是如何工作的,因?yàn)槟憧梢栽谥暗奈恼轮姓业健?/p>

我將通過一個我所使用的 docker-compose.yml 文件來啟動:

version: '2'
services:
    books-service:
        container_name: books-api
        build: .

    reverse-proxy:
        container_name: reverse-proxy
        image: nginx
        ports:
         - "9090:8080"
        volumes:
         - ./proxy.conf:/etc/nginx/conf.d/default.conf

這是版本 2 語法,所以為了能夠正常工作,你至少需要 1.6 版本的 Docker Compose。

這個文件告訴 Docker 創(chuàng)建兩個服務(wù):一個是給應(yīng)用的,另一個是給 Nginx 反向代理服務(wù)器的。

BOOKS-SERVICE

Linux怎么通過Docker托管.NET Core
這個與 docker-compose.yml 相同目錄下的 Dockerfile 構(gòu)建的容器叫做 books-api。注意這個容器不需要發(fā)布任何端口,因?yàn)橹灰軌驈姆聪虼矸?wù)器訪問它就可以,而不需要從主機(jī)操作系統(tǒng)訪問它。

REVERSE-PROXY

這將基于 nginx 鏡像啟動一個叫做 reverse-proxy 的容器,并將位于當(dāng)前目錄下的 proxy.conf 文件掛載為配置。它把主機(jī)上的 9090 端口映射到容器中的 8080 端口,這將允許我們在http://localhost:9090上通過主機(jī)訪問容器。

proxy.conf 文件看起來像下面這樣:

server {
    listen 8080;

    location / {
      proxy_pass http://books-service:5000;
    }
}

這兒的關(guān)鍵點(diǎn)是我們現(xiàn)在可以通過名字引用books-service,因此我們不需要知道 books-api 這個容器的 IP 地址!

現(xiàn)在我們可以通過一個運(yùn)行著的反向代理啟動兩個容器(-d意味著這是獨(dú)立的,因此我們不能看到來自容器的輸出):

docker compose up -d

驗(yàn)證我們所創(chuàng)建的容器:

docker ps

最后來驗(yàn)證我們可以通過反向代理來控制該 API :

curl -i http://localhost:9090/api/books

怎么做到的?

Docker Compose 通過創(chuàng)建一個新的叫做 mvclibrary_default 的虛擬網(wǎng)絡(luò)來實(shí)現(xiàn)這件事,這個虛擬網(wǎng)絡(luò)同時用于books-api 和 reverse-proxy 容器(名字是基于 docker-compose.yml 文件的父目錄)。

通過docker network ls來驗(yàn)證網(wǎng)絡(luò)已經(jīng)存在:

Linux怎么通過Docker托管.NET Core

你可以使用 docker network inspect mvclibrary_default 來看到新的網(wǎng)絡(luò)的細(xì)節(jié):

Linux怎么通過Docker托管.NET Core

注意容器的兩個別名("Aliases")是容器標(biāo)識符(3c42db680459)和由 docker-compose.yml 給出的服務(wù)名(books-service)。我們通過books-service 別名在自定義 Nginx 配置文件中來引用應(yīng)用程序的容器。這本可以通過 docker network create 手動創(chuàng)建,但是我喜歡用 Docker Compose,因?yàn)樗梢愿蓛艉啙嵉貙⑷萜鲃?chuàng)建和依存捆綁在一起。

結(jié)論

所以現(xiàn)在我可以通過幾個簡單的步驟在 Linux 系統(tǒng)上用 Nginx 運(yùn)行應(yīng)用程序,不需要對主機(jī)操作系統(tǒng)做任何長期的改變:

git clone https://github.com/niksoper/aspnet5-books.git
cd aspnet5-books/src/MvcLibrary
git checkout blog-docker
docker-compose up -d
curl -i http://localhost:9090/api/books

到此,關(guān)于“Linux怎么通過Docker托管.NET Core”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI