這篇文章主要介紹“Linux怎么通過(guò)Docker托管.NET Core”,在日常操作中,相信很多人在Linux怎么通過(guò)Docker托管.NET Core問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對大家解答”Linux怎么通過(guò)Docker托管.NET Core”的疑惑有所幫助!接下來(lái),請跟著(zhù)小編一起來(lái)學(xué)習吧!
轉換到 .NET CORE 1.0
自然地,當我考慮如何把 API 從 .NET Core RC1 升級到 .NET Core 1.0 時(shí)想到的第一個(gè)求助的地方就是谷歌搜索。我是按照下面這兩條非常全面的指導來(lái)進(jìn)行升級的:
從 DNX 遷移到 .NET Core CLI
從 ASP.NET 5 RC1 遷移到 ASP.NET Core 1.0
當你遷移代碼的時(shí)候,我建議仔細閱讀這兩篇指導,因為我在沒(méi)有閱讀第一篇指導的情況下又嘗試瀏覽第二篇,結果感到非常迷惑和沮喪。
我不想描述細節上的改變因為你可以看 GitHub 上的提交。這兒是我所作改變的總結:
更新 global.json 和project.json 上的版本號
刪除 project.json上的廢棄章節
使用輕型 ControllerBase 而不是 Controller, 因為我不需要與 MVC 視圖相關(guān)的方法(這是一個(gè)可選的改變)。
從輔助方法中去掉 Http 前綴,比如:HttpNotFound -> NotFound
LogVerbose -> LogTrace
名字空間改變: Microsoft.AspNetCore.*
在Startup 中使用SetBasePath(沒(méi)有它 appsettings.json 將不會(huì )被發(fā)現)
通過(guò) WebHostBuilder 來(lái)運行而不是通過(guò)WebApplication.Run 來(lái)運行
刪除 Serilog(在寫(xiě)文章的時(shí)候,它不支持 .NET Core 1.0)
唯一令我真正頭疼的事是需要移動(dòng) Serilog。我本可以實(shí)現自己的文件記錄器,但是我刪除了文件記錄功能,因為我不想為了這次操作在這件事情上花費精力。
不幸的是,將有大量的第三方開(kāi)發(fā)者扮演追趕 .NET Core 1.0 的角色,我非常同情他們,因為他們通常在休息時(shí)間還堅持工作但卻依舊根本無(wú)法接近靠攏微軟的可用資源。我建議閱讀 Travis Illig 的文章 .NET Core 1.0 發(fā)布了,但 Autofac 在哪兒?這是一篇關(guān)于第三方開(kāi)發(fā)者觀(guān)點(diǎn)的文章。
做了這些改變以后,我可以從project.json 目錄恢復、構建并運行 dotnet,可以看到 API 又像以前一樣工作了。
通過(guò) Docker 運行
在我寫(xiě)這篇文章的時(shí)候, Docker 只能夠在 Linux 系統上工作。在 Windows 系統和 OS X 上有 beta 支持 Docker,但是它們都必須依賴(lài)于虛擬化技術(shù),因此,我選擇把 Ubuntu 14.04 當作虛擬機來(lái)運行。如果你還沒(méi)有安裝過(guò) Docker,請按照指導來(lái)安裝。
我最近閱讀了一些關(guān)于 Docker 的東西,但我直到現在還沒(méi)有真正用它來(lái)干任何事。我假設讀者還沒(méi)有關(guān)于 Docker 的知識,因此我會(huì )解釋我所使用的所有命令。
HELLO DOCKER
在 Ubuntu 上安裝好 Docker 之后,我所進(jìn)行的下一步就是按照 https://www.microsoft.com/net/core#docker 上的介紹來(lái)開(kāi)始運行 .NET Core 和 Docker。
首先啟動(dòng)一個(gè)已安裝有 .NET Core 的容器。
docker run -it microsoft/dotnet:latest
-it 選項表示交互,所以你執行這條命令之后,你就處于容器之內了,可以如你所希望的那樣執行任何 bash 命令。
然后我們可以執行下面這五條命令來(lái)在 Docker 內部運行起來(lái)微軟 .NET Core 控制臺應用程序示例。
mkdir hwapp cd hwapp dotnet new dotnet restore dotnet run
你可以通過(guò)運行 exit 來(lái)離開(kāi)容器,然后運行 Docker ps -a 命令,這會(huì )顯示你創(chuàng )建的那個(gè)已經(jīng)退出的容器。你可以通過(guò)上運行命令 Docker rm <container_name> 來(lái)清除容器。
掛載源代碼
我的下一步驟是使用和上面相同的 microsoft/dotnet 鏡像,但是將為我們的應用程序以數據卷的方式掛載上源代碼。
首先簽出有相關(guān)提交的倉庫:
git clone https://github.com/niksoper/aspnet5-books.git cd aspnet5-books/src/MvcLibrary git checkout dotnet-core-1.0
現在啟動(dòng)一個(gè)容器來(lái)運行 .NET Core 1.0,并將源代碼放在/book 下。注意更改 /path/to/repo這部分文件來(lái)匹配你的電腦:
docker run -it / -v /path/to/repo/aspnet5-books/src/MvcLibrary:/books / microsoft/dotnet:latest
現在你可以在容器中運行應用程序了!
cd /books dotnet restore dotnet run
作為一個(gè)概念性展示這的確很棒,但是我們可不想每次運行一個(gè)程序都要考慮如何把源代碼安裝到容器里。
增加一個(gè) DOCKERFILE
我的下一步驟是引入一個(gè) Dockerfile,這可以讓?xiě)贸绦蚝苋菀自谧约旱娜萜鲀葐?dòng)。
我的 Dockerfile 和 project.json 一樣位于 src/MvcLibrary目錄下,看起來(lái)像下面這樣:
FROM microsoft/dotnet:latest # 為應用程序源代碼創(chuàng )建目錄 RUN mkdir -p /usr/src/books WORKDIR /usr/src/books # 復制源代碼并恢復依賴(lài)關(guān)系 COPY . /usr/src/books RUN dotnet restore # 暴露端口并運行應用程序 EXPOSE 5000 CMD [ "dotnet", "run" ]
嚴格來(lái)說(shuō),RUN mkdir -p /usr/src/books 命令是不需要的,因為 COPY 會(huì )自動(dòng)創(chuàng )建丟失的目錄。
Docker 鏡像是按層建立的,我們從包含 .NET Core 的鏡像開(kāi)始,添加另一個(gè)從源代碼生成應用程序,然后運行這個(gè)應用程序的層。
添加了 Dockerfile 以后,我通過(guò)運行下面的命令來(lái)生成一個(gè)鏡像,并使用生成的鏡像啟動(dòng)一個(gè)容器(確保在和 Dockerfile 相同的目錄下進(jìn)行操作,并且你應該使用自己的用戶(hù)名)。
docker build -t niksoper/netcore-books . docker run -it niksoper/netcore-books
你應該看到程序能夠和之前一樣的運行,不過(guò)這一次我們不需要像之前那樣安裝源代碼,因為源代碼已經(jīng)包含在 docker 鏡像里面了。
暴露并發(fā)布端口
這個(gè) API 并不是特別有用,除非我們需要從容器外面和它進(jìn)行通信。 Docker 已經(jīng)有了暴露和發(fā)布端口的概念,但這是兩件完全不同的事。
據 Docker 官方文檔:
EXPOSE指令通知 Docker 容器在運行時(shí)監聽(tīng)特定的網(wǎng)絡(luò )端口。EXPOSE指令不能夠讓容器的端口可被主機訪(fǎng)問(wèn)。要使可被訪(fǎng)問(wèn),你必須通過(guò) -p 標志來(lái)發(fā)布一個(gè)端口范圍或者使用 -p 標志來(lái)發(fā)布所有暴露的端口
EXPOSE 指令只是將元數據添加到鏡像上,所以你可以如文檔中說(shuō)的認為它是鏡像消費者。從技術(shù)上講,我本應該忽略 EXPOSE 5000 這行指令,因為我知道 API 正在監聽(tīng)的端口,但把它們留下很有用的,并且值得推薦。
在這個(gè)階段,我想直接從主機訪(fǎng)問(wèn)這個(gè) API ,因此我需要通過(guò)-p 指令來(lái)發(fā)布這個(gè)端口,這將允許請求從主機上的端口 5000 轉發(fā)到容器上的端口 5000,無(wú)論這個(gè)端口是不是之前通過(guò) Dockerfile 暴露的。
docker run -d -p 5000:5000 niksoper/netcore-books
通過(guò) -d 指令告訴 docker 在分離模式下運行容器,因此我們不能看到它的輸出,但是它依舊會(huì )運行并監聽(tīng)端口 5000。你可以通過(guò) docker ps來(lái)證實(shí)這件事。
因此,接下來(lái)我準備從主機向容器發(fā)起一個(gè)請求來(lái)慶祝一下:
curl http://localhost:5000/api/books
它不工作。
重復進(jìn)行相同 curl 請求,我看到了兩個(gè)錯誤:要么是 curl: (56) Recv failure: Connection reset by peer,要么是 curl: (52) Empty reply from server。
我返回去看 docker run 的文檔,然后再次檢查我所使用的 -p 選項以及 Dockerfile 中的 EXPOSE指令是否正確。我沒(méi)有發(fā)現任何問(wèn)題,這讓我開(kāi)始有些沮喪。
重新振作起來(lái)以后,我決定去咨詢(xún)當地的一個(gè) Scott Logic DevOps 大師 - Dave Wybourn(也在這篇 Docker Swarm 的文章里提到過(guò)),他的團隊也曾遇到這個(gè)實(shí)際問(wèn)題。這個(gè)問(wèn)題是我沒(méi)有配置過(guò) Kestral,這是一個(gè)全新的輕量級、跨平臺 web ,用于 .NET Core 。
默認情況下, Kestrel 會(huì )監聽(tīng) http://localhost:5000。但問(wèn)題是,這兒的localhost是一個(gè)回路接口。
據維基百科:
在計算機網(wǎng)絡(luò )中,localhost 是一個(gè)代表本機的主機名。本地主機可以通過(guò)網(wǎng)絡(luò )回路接口訪(fǎng)問(wèn)在主機上運行的網(wǎng)絡(luò )服務(wù)。通過(guò)使用回路接口可以繞過(guò)任何硬件網(wǎng)絡(luò )接口。
當運行在容器內時(shí)這是一個(gè)問(wèn)題,因為 localhost 只能夠在容器內訪(fǎng)問(wèn)。解決方法是更新 Startup.cs里的 Main 方法來(lái)配置 Kestral 監聽(tīng)的 URL:
public static void Main(string[] args) { var host = new WebHostBuilder() .UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .UseUrls("http://*:5000") // 在所有網(wǎng)絡(luò )接口上監聽(tīng)端口 5000 .UseIISIntegration() .UseStartup<Startup>() .Build(); host.Run(); }
通過(guò)這些額外的配置,我可以重建鏡像,并在容器中運行應用程序,它將能夠接收來(lái)自主機的請求:
docker build -t niksoper/netcore-books . docker run -d -p 5000:5000 niksoper/netcore-books curl -i http://localhost:5000/api/books
我現在得到下面這些相應:
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)境中運行 KESTREL
微軟的介紹:
Kestrel 可以很好的處理來(lái)自 ASP.NET 的動(dòng)態(tài)內容,然而,網(wǎng)絡(luò )服務(wù)部分的特性沒(méi)有如 IIS,Apache 或者 Nginx 那樣的全特性服務(wù)器那么好。反向代理服務(wù)器可以讓你不用去做像處理靜態(tài)內容、緩存請求、壓縮請求、SSL 端點(diǎn)這樣的來(lái)自 HTTP 服務(wù)器的工作。
因此我需要在我的 Linux 機器上把 Nginx 設置成一個(gè)反向代理服務(wù)器。微軟介紹了如何發(fā)布到 Linux 生產(chǎn)環(huán)境下的指導教程。我把說(shuō)明總結在這兒:
通過(guò) dotnet publish 來(lái)給應用程序產(chǎn)生一個(gè)自包含包。
把已發(fā)布的應用程序復制到服務(wù)器上
安裝并配置 Nginx(作為反向代理服務(wù)器)
安裝并配置 supervisor(用于確保 Nginx 服務(wù)器處于運行狀態(tài)中)
安裝并配置 AppArmor(用于限制應用的資源使用)
配置服務(wù)器防火墻
安全加固 Nginx(從源代碼構建和配置 SSL)
這些內容已經(jīng)超出了本文的范圍,因此我將側重于如何把 Nginx 配置成一個(gè)反向代理服務(wù)器。自然地,我通過(guò) Docker 來(lái)完成這件事。
在另一個(gè)容器中運行NGINX
我的目標是在第二個(gè) Docker 容器中運行 Nginx 并把它配置成我們的應用程序容器的反向代理服務(wù)器。
我使用的是來(lái)自 Docker Hub 的官方 Nginx 鏡像。首先我嘗試這樣做:
docker run -d -p 8080:80 --name web nginx
這啟動(dòng)了一個(gè)運行 Nginx 的容器并把主機上的 8080 端口映射到了容器的 80 端口上?,F在在瀏覽器中打開(kāi)網(wǎng)址 http://localhost:8080 會(huì )顯示出 Nginx 的默認登錄頁(yè)面。
現在我們證實(shí)了運行 Nginx 是多么的簡(jiǎn)單,我們可以關(guān)閉這個(gè)容器。
docker rm -f web
把 NGINX 配置成一個(gè)反向代理服務(wù)器
可以通過(guò)像下面這樣編輯位于 /etc/nginx/conf.d/default.conf 的配置文件,把 Nginx 配置成一個(gè)反向代理服務(wù)器:
server { listen 80; location / { proxy_pass http://localhost:6666; } }
通過(guò)上面的配置可以讓 Nginx 將所有對根目錄的訪(fǎng)問(wèn)請求代理到 http://localhost:6666。記住這里的 localhost 指的是運行 Nginx 的容器。我們可以在 Nginx容器內部利用卷來(lái)使用我們自己的配置文件:
docker run -d -p 8080:80 / -v /path/to/my.conf:/etc/nginx/conf.d/default.conf / nginx
注意:這把一個(gè)單一文件從主機映射到容器中,而不是一個(gè)完整目錄。
在容器間進(jìn)行通信
Docker 允許內部容器通過(guò)共享虛擬網(wǎng)絡(luò )進(jìn)行通信。默認情況下,所有通過(guò) Docker 守護進(jìn)程啟動(dòng)的容器都可以訪(fǎng)問(wèn)一種叫做“橋”的虛擬網(wǎng)絡(luò )。這使得一個(gè)容器可以被另一個(gè)容器在相同的網(wǎng)絡(luò )上通過(guò) IP 地址和端口來(lái)引用。
你可以通過(guò)監測inspect容器來(lái)找到它的 IP 地址。我將從之前創(chuàng )建的 niksoper/netcore-books 鏡像中啟動(dòng)一個(gè)容器并監測inspect它:
docker run -d -p 5000:5000 --name books niksoper/netcore-books docker inspect books
我們可以看到這個(gè)容器的 IP 地址是 "IPAddress": "172.17.0.3"。
所以現在如果我創(chuàng )建下面的 Nginx 配置文件,并使用這個(gè)文件啟動(dòng)一個(gè) Nginx 容器, 它將代理請求到我的 API :
server { listen 80; location / { proxy_pass http://172.17.0.3:5000; } }
現在我可以使用這個(gè)配置文件啟動(dòng)一個(gè) Nginx 容器(注意我把主機上的 8080 端口映射到了 Nginx 容器上的 80 端口):
docker run -d -p 8080:80 / -v ~/dev/nginx/my.nginx.conf:/etc/nginx/conf.d/default.conf / nginx
一個(gè)到http://localhost:8080 的請求將被代理到應用上。注意下面 curl 響應的 Server 響應頭:
DOCKER COMPOSE
在這個(gè)地方,我為自己的進(jìn)步而感到高興,但我認為一定還有更好的方法來(lái)配置 Nginx,可以不需要知道應用程序容器的確切 IP 地址。另一個(gè)當地的 Scott Logic DevOps 大師 Jason Ebbin 在這個(gè)地方進(jìn)行了改進(jìn),并建議使用 Docker Compose。
概況描述一下,Docker Compose 使得一組通過(guò)聲明式語(yǔ)法互相連接的容器很容易啟動(dòng)。我不想再細說(shuō) Docker Compose 是如何工作的,因為你可以在之前的文章中找到。
我將通過(guò)一個(gè)我所使用的 docker-compose.yml 文件來(lái)啟動(dòng):
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 語(yǔ)法,所以為了能夠正常工作,你至少需要 1.6 版本的 Docker Compose。
這個(gè)文件告訴 Docker 創(chuàng )建兩個(gè)服務(wù):一個(gè)是給應用的,另一個(gè)是給 Nginx 反向代理服務(wù)器的。
BOOKS-SERVICE
這個(gè)與 docker-compose.yml 相同目錄下的 Dockerfile 構建的容器叫做 books-api。注意這個(gè)容器不需要發(fā)布任何端口,因為只要能夠從反向代理服務(wù)器訪(fǎng)問(wèn)它就可以,而不需要從主機操作系統訪(fǎng)問(wèn)它。
REVERSE-PROXY
這將基于 nginx 鏡像啟動(dòng)一個(gè)叫做 reverse-proxy 的容器,并將位于當前目錄下的 proxy.conf 文件掛載為配置。它把主機上的 9090 端口映射到容器中的 8080 端口,這將允許我們在http://localhost:9090上通過(guò)主機訪(fǎng)問(wèn)容器。
proxy.conf 文件看起來(lái)像下面這樣:
server { listen 8080; location / { proxy_pass http://books-service:5000; } }
這兒的關(guān)鍵點(diǎn)是我們現在可以通過(guò)名字引用books-service,因此我們不需要知道 books-api 這個(gè)容器的 IP 地址!
現在我們可以通過(guò)一個(gè)運行著(zhù)的反向代理啟動(dòng)兩個(gè)容器(-d意味著(zhù)這是獨立的,因此我們不能看到來(lái)自容器的輸出):
docker compose up -d
驗證我們所創(chuàng )建的容器:
docker ps
最后來(lái)驗證我們可以通過(guò)反向代理來(lái)控制該 API :
curl -i http://localhost:9090/api/books
怎么做到的?
Docker Compose 通過(guò)創(chuàng )建一個(gè)新的叫做 mvclibrary_default 的虛擬網(wǎng)絡(luò )來(lái)實(shí)現這件事,這個(gè)虛擬網(wǎng)絡(luò )同時(shí)用于books-api 和 reverse-proxy 容器(名字是基于 docker-compose.yml 文件的父目錄)。
通過(guò)docker network ls來(lái)驗證網(wǎng)絡(luò )已經(jīng)存在:
你可以使用 docker network inspect mvclibrary_default 來(lái)看到新的網(wǎng)絡(luò )的細節:
注意容器的兩個(gè)別名("Aliases")是容器標識符(3c42db680459)和由 docker-compose.yml 給出的服務(wù)名(books-service)。我們通過(guò)books-service 別名在自定義 Nginx 配置文件中來(lái)引用應用程序的容器。這本可以通過(guò) docker network create 手動(dòng)創(chuàng )建,但是我喜歡用 Docker Compose,因為它可以干凈簡(jiǎn)潔地將容器創(chuàng )建和依存捆綁在一起。
結論
所以現在我可以通過(guò)幾個(gè)簡(jiǎn)單的步驟在 Linux 系統上用 Nginx 運行應用程序,不需要對主機操作系統做任何長(chá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
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站