您好,登錄后才能下訂單哦!
這篇文章主要介紹“Linux中怎么使用Docker托管.NET Core”,在日常操作中,相信很多人在Linux中怎么使用Docker托管.NET Core問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Linux中怎么使用Docker托管.NET Core”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
在 Ubuntu 上安裝好 Docker 之后
首先啟動一個已安裝有 .NET Core 的容器。
docker run -it microsoft/dotnet:latest
-it 選項表示交互,所以你執(zhí)行這條命令之后,你就處于容器之內(nèi)了,可以如你所希望的那樣執(zhí)行任何 bash 命令。
然后我們可以執(zhí)行下面這五條命令來在 Docker 內(nèi)部運行起來微軟 .NET Core 控制臺應用程序示例。
mkdir hwappcd hwapp dotnet new dotnet restore dotnet run
你可以通過運行 exit 來離開容器,然后運行 Docker ps -a 命令,這會顯示你創(chuàng)建的那個已經(jīng)退出的容器。你可以通過上運行命令 Docker rm
我的下一步驟是使用和上面相同的 microsoft/dotnet 鏡像,但是將為我們的應用程序以數(shù)據(jù)卷的方式掛載上源代碼。 首先簽出有相關提交的倉庫:
git clone https://github.com/niksoper/aspnet5-books.gitcd aspnet5-books/src/MvcLibrary git checkout dotnet-core-1.0
現(xià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)在你可以在容器中運行應用程序了!
cd /books dotnet restore dotnet run
作為一個概念性展示這的確很棒,但是我們可不想每次運行一個程序都要考慮如何把源代碼安裝到容器里。
我的下一步驟是引入一個 Dockerfile,這可以讓應用程序很容易在自己的容器內(nèi)啟動。
我的 Dockerfile 和 project.json 一樣位于 src/MvcLibrary目錄下,看起來像下面這樣:
FROM microsoft/dotnet:latest# 為應用程序源代碼創(chuàng)建目錄RUN mkdir -p /usr/src/books WORKDIR /usr/src/books# 復制源代碼并恢復依賴關系COPY . /usr/src/books RUN dotnet restore# 暴露端口并運行應用程序EXPOSE 5000 CMD [ "dotnet", "run" ]
嚴格來說,RUN mkdir -p /usr/src/books 命令是不需要的,因為 COPY 會自動創(chuàng)建丟失的目錄。
Docker 鏡像是按層建立的,我們從包含 .NET Core 的鏡像開始,添加另一個從源代碼生成應用程序,然后運行這個應用程序的層。
添加了 Dockerfile 以后,我通過運行下面的命令來生成一個鏡像,并使用生成的鏡像啟動一個容器(確保在和 Dockerfile 相同的目錄下進行操作,并且你應該使用自己的用戶名)。
docker build -t niksoper/netcore-books . docker run -it niksoper/netcore-books
你應該看到程序能夠和之前一樣的運行,不過這一次我們不需要像之前那樣安裝源代碼,因為源代碼已經(jīng)包含在 docker 鏡像里面了。
這個 API 并不是特別有用,除非我們需要從容器外面和它進行通信。 Docker 已經(jīng)有了暴露和發(fā)布端口的概念,但這是兩件完全不同的事。
據(jù) Docker 官方文檔: EXPOSE指令通知 Docker 容器在運行時監(jiān)聽特定的網(wǎng)絡端口。EXPOSE指令不能夠讓容器的端口可被主機訪問。要使可被訪問,你必須通過 -p 標志來發(fā)布一個端口范圍或者使用 -p 標志來發(fā)布所有暴露的端口 EXPOSE 指令只是將元數(shù)據(jù)添加到鏡像上,所以你可以如文檔中說的認為它是鏡像消費者。從技術上講,我本應該忽略 EXPOSE 5000 這行指令,因為我知道 API 正在監(jiān)聽的端口,但把它們留下很有用的,并且值得推薦。
在這個階段,我想直接從主機訪問這個 API ,因此我需要通過-p 指令來發(fā)布這個端口,這將允許請求從主機上的端口 5000 轉(zhuǎn)發(fā)到容器上的端口 5000,無論這個端口是不是之前通過 Dockerfile 暴露的。
docker run -d -p 5000:5000 niksoper/netcore-books
通過 -d 指令告訴 docker 在分離模式下運行容器,因此我們不能看到它的輸出,但是它依舊會運行并監(jiān)聽端口 5000。你可以通過 docker ps來證實這件事。
因此,接下來我準備從主機向容器發(fā)起一個請求來慶祝一下:
curl http://localhost:5000/api/books
它不工作。
重復進行相同 curl 請求,我看到了兩個錯誤:要么是 curl: (56) Recv failure: Connection reset by peer,要么是 curl: (52) Empty reply from server。
我返回去看 docker run 的文檔,然后再次檢查我所使用的 -p 選項以及 Dockerfile 中的 EXPOSE指令是否正確。我沒有發(fā)現(xiàn)任何問題,這讓我開始有些沮喪。
重新振作起來以后,我決定去咨詢當?shù)氐囊粋€ Scott Logic DevOps 大師 – Dave Wybourn(也在這篇 Docker Swarm 的文章里提到過),他的團隊也曾遇到這個實際問題。這個問題是我沒有配置過 Kestral,這是一個全新的輕量級、跨平臺 web 服務器,用于 .NET Core 。
默認情況下, Kestrel 會監(jiān)聽 http://localhost:5000。但問題是,這兒的localhost是一個回路接口。
據(jù)維基百科: 在計算機網(wǎng)絡中,localhost 是一個代表本機的主機名。本地主機可以通過網(wǎng)絡回路接口訪問在主機上運行的網(wǎng)絡服務。通過使用回路接口可以繞過任何硬件網(wǎng)絡接口。 當運行在容器內(nèi)時這是一個問題,因為 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)絡接口上監(jiān)聽端口 5000 .UseIISIntegration() .UseStartup() .Build(); host.Run(); }
通過這些額外的配置,我可以重建鏡像,并在容器中運行應用程序,它將能夠接收來自主機的請求:
docker build -t niksoper/netcore-books . docker run -d -p 5000:5000 niksoper/netcore-books curl -i http://localhost:5000/api/books
我現(xiàn)在得到下面這些相應:
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"}]
微軟的介紹: Kestrel 可以很好的處理來自 ASP.NET 的動態(tài)內(nèi)容,然而,網(wǎng)絡服務部分的特性沒有如 IIS,Apache 或者 Nginx 那樣的全特性服務器那么好。反向代理服務器可以讓你不用去做像處理靜態(tài)內(nèi)容、緩存請求、壓縮請求、SSL 端點這樣的來自 HTTP 服務器的工作。 因此我需要在我的 Linux 機器上把 Nginx 設置成一個反向代理服務器。微軟介紹了如何發(fā)布到 Linux 生產(chǎn)環(huán)境下的指導教程。我把說明總結(jié)在這兒:
這些內(nèi)容已經(jīng)超出了本文的范圍,因此我將側(cè)重于如何把 Nginx 配置成一個反向代理服務器。自然地,我通過 Docker 來完成這件事。
我的目標是在第二個 Docker 容器中運行 Nginx 并把它配置成我們的應用程序容器的反向代理服務器。
我使用的是來自 Docker Hub 的官方 Nginx 鏡像。首先我嘗試這樣做:
docker run -d -p 8080:80 --name web nginx
這啟動了一個運行 Nginx 的容器并把主機上的 8080 端口映射到了容器的 80 端口上?,F(xiàn)在在瀏覽器中打開網(wǎng)址 http://localhost:8080 會顯示出 Nginx 的默認登錄頁面。
現(xiàn)在我們證實了運行 Nginx 是多么的簡單,我們可以關閉這個容器。
docker rm -f web
可以通過像下面這樣編輯位于 /etc/nginx/conf.d/default.conf 的配置文件,把 Nginx 配置成一個反向代理服務器:
server { listen 80; location / { proxy_pass http://localhost:6666; } }
通過上面的配置可以讓 Nginx 將所有對根目錄的訪問請求代理到 http://localhost:6666。記住這里的 localhost 指的是運行 Nginx 的容器。我們可以在 Nginx容器內(nèi)部利用卷來使用我們自己的配置文件:
docker run -d -p 8080:80 / -v /path/to/my.conf:/etc/nginx/conf.d/default.conf / nginx
注意:這把一個單一文件從主機映射到容器中,而不是一個完整目錄。
Docker 允許內(nèi)部容器通過共享虛擬網(wǎng)絡進行通信。默認情況下,所有通過 Docker 守護進程啟動的容器都可以訪問一種叫做“橋”的虛擬網(wǎng)絡。這使得一個容器可以被另一個容器在相同的網(wǎng)絡上通過 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
我們可以看到這個容器的 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 容器(注意我把主機上的 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 的請求將被代理到應用上。注意下面 curl 響應的 Server 響應頭:
DOCKER COMPOSE
在這個地方,我為自己的進步而感到高興,但我認為一定還有更好的方法來配置 Nginx,可以不需要知道應用程序容器的確切 IP 地址。另一個當?shù)氐?Scott Logic DevOps 大師 Jason Ebbin 在這個地方進行了改進,并建議使用 Docker Compose。
概況描述一下,Docker Compose 使得一組通過聲明式語法互相連接的容器很容易啟動。我不想再細說 Docker Compose 是如何工作的,因為你可以在之前的文章中找到。
我將通過一個我所使用的 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)建兩個服務:一個是給應用的,另一個是給 Nginx 反向代理服務器的。
這個與 docker-compose.yml 相同目錄下的 Dockerfile 構建的容器叫做 books-api。注意這個容器不需要發(fā)布任何端口,因為只要能夠從反向代理服務器訪問它就可以,而不需要從主機操作系統(tǒng)訪問它。
這將基于 nginx 鏡像啟動一個叫做 reverse-proxy 的容器,并將位于當前目錄下的 proxy.conf 文件掛載為配置。它把主機上的 9090 端口映射到容器中的 8080 端口,這將允許我們在http://localhost:9090上通過主機訪問容器。
proxy.conf 文件看起來像下面這樣:
server { listen 8080; location / { proxy_pass http://books-service:5000; } }
這兒的關鍵點是我們現(xiàn)在可以通過名字引用books-service,因此我們不需要知道 books-api 這個容器的 IP 地址!
現(xiàn)在我們可以通過一個運行著的反向代理啟動兩個容器(-d意味著這是獨立的,因此我們不能看到來自容器的輸出):
docker compose up -d
驗證我們所創(chuàng)建的容器:
docker ps
最后來驗證我們可以通過反向代理來控制該 API :
curl -i http://localhost:9090/api/books
Docker Compose 通過創(chuàng)建一個新的叫做 mvclibrary_default 的虛擬網(wǎng)絡來實現(xiàn)這件事,這個虛擬網(wǎng)絡同時用于books-api 和 reverse-proxy 容器(名字是基于 docker-compose.yml 文件的父目錄)。
通過docker network ls來驗證網(wǎng)絡已經(jīng)存在:
你可以使用 docker network inspect mvclibrary_default 來看到新的網(wǎng)絡的細節(jié):
注意 Docker 已經(jīng)給網(wǎng)絡分配了子網(wǎng):”Subnet”: “172.18.0.0/16″。/16 部分是無類域內(nèi)路由選擇(CIDR),完整的解釋已經(jīng)超出了本文的范圍,但 CIDR 只是表示 IP 地址范圍。運行 docker network inspect bridge 顯示子網(wǎng):”Subnet”: “172.17.0.0/16″,因此這兩個網(wǎng)絡是不重疊的。
現(xiàn)在用 docker inspect books-api 來確認應用程序的容器正在使用該網(wǎng)絡:
注意容器的兩個別名(”Aliases”)是容器標識符(3c42db680459)和由 docker-compose.yml 給出的服務名(books-service)。我們通過books-service 別名在自定義 Nginx 配置文件中來引用應用程序的容器。這本可以通過 docker network create 手動創(chuàng)建,但是我喜歡用 Docker Compose,因為它可以干凈簡潔地將容器創(chuàng)建和依存捆綁在一起。
所以現(xiàn)在我可以通過幾個簡單的步驟在 Linux 系統(tǒng)上用 Nginx 運行應用程序,不需要對主機操作系統(tǒng)做任何長期的改變:
git clone https://github.com/niksoper/aspnet5-books.gitcd aspnet5-books/src/MvcLibrary git checkout blog-docker docker-compose up -d curl -i http://localhost:9090/api/books
到此,關于“Linux中怎么使用Docker托管.NET Core”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。