Docker & ASP.NET Core (1):把程式碼連線到容器

solenovex發表於2018-11-20

和這種蛋糕一樣,Docker的容器和映象也是使用類似的分層檔案系統構建而成的。

這樣做的好處就是可以節省硬碟空間,也利於複用等等。因為Docker基於映象建立容器的時候,其映象是共享的;而且映象裡面的層如果已存在,也無需再下載。

 

下面拉取一個mongodb的映象,拉取的過程中可以看到:

圖中紅框範圍內的就是mongo映象的不同分層,也就是映象中的分層檔案系統。

 

然而這些映象層是隻讀的:

這樣的限制多少看起來有點嚴格,如果你想使用該映象讀寫資料庫怎麼辦?或者記錄Log到檔案,或者在容器執行的時候替換一些原始碼該怎麼辦?

 

幸運的時候使用該映象的容器會有可用於讀寫的"薄薄"一層:

從圖中也可以看出容器和映象的不同之處。

 

你可以在容器層進行寫入,但是如果容器被刪除了,那麼可讀寫的這一層也會被刪除。

這樣就不太友好了,而這時我們可以使用Volume(卷)

 

下面就是這個問題,如何把原始碼裝進容器裡?

1.可以在製做映象的時候把原始碼直接寫入映象。(這個先不考慮)

2.把原始碼裝進容器的可讀寫層。(這個是我要介紹的)

 

Volume是什麼?

  • Volume(卷)是容器中一個特別種類的目錄,通常叫做資料volume,顧名思義,裡面可以放置各種型別的資料,例如程式碼、日誌檔案、資料檔案等等。
  • Volume可以在容器間被共享和複用。可以讓多個容器對同一個volume進行讀寫,也可以讓一個容器讀寫多個volume。
  • 對映象的更新並不會影響volume。
  • Volume是被持久化的,即使容器刪除了,它仍然還在。

 

可以這樣去理解Volume,如果有一個容器,那麼我們可以在這個容器裡面定義一個Volume:

 

那麼想要寫到哪裡去呢?

可以讓Docker自己搞定,或者你也可以自定義。

讓Docker決定寫入的位置

先介紹第一種情況,當你寫入到volume的時候,比如在Docker容器裡的程式碼對/var/www做了一個寫入的操作,那該目錄其實就是你docker host裡面的一個裝載的資料夾(mounted folder)的別名。Docker host也就是容器的宿主,如果你使用的是Linux系統或Windows 2016及以上版本的系統,那麼該宿主就是作業系統。容器也就是執行在該系統上。

那麼在這個例子裡,我們寫入的這個volume,它可以不是容器的可讀寫層,它實際上可以寫入docker host的裝載的資料夾,也就是作業系統的資料夾。即使你把容器刪除了,docker host裡的資料夾仍在健在。

 

通常我們使用如下命令來執行容器:

docker run -p 8000:80 microsoft/dotnet-samples:aspnetapp

 

而我們可以使用-v引數來指定volume:

docker run -p 8000:80 -v /var/www microsoft/dotnet-samples:aspnetapp

這樣的話,/var/www只是容器Volume的別名,實際被寫入的區域在Docker Host裡,docker會自動的建立這個區域。

 

可以使用docker inspect 容器名這個命令來檢視相關的路徑。

執行該命令後的結果中會顯示如下部分Mounts:

其中Destination是volume在容器裡的地址(別名),而Source則是Volume在宿主中的地址。

以上這部分介紹的就是讓Docker來建立寫入的目錄。

 

自定義寫入的位置

下面講一下如何自定義這個目錄的地址。

這樣就對我們開發寫程式碼比較友好了,我的程式碼存放於Windows/Mac系統中,然後我們讓Volume讀寫我們程式碼所在的區域。

那麼應該使用哪個Docker命令呢?

docker run -p 8000:80 -v ${PWD}:/var/www microsoft/dotnet-samples:aspnetapp

使用-v在容器裡建立一個volume,它在容器的地址是/var/www,但是當你對它進行讀寫操作時,它實際上找的是宿主的地址,在這裡也就是當前的工作目錄(curent working directory)。

 

如果你這時再執行docker inspect命令,其結果大概如下:

 

把ASP.NET Core的原始碼連線到Volume

首先使用dotnet cli或者VS建立一個ASP.NET Core專案:

 

然後使用dotnet run測試一下網站是否能正常執行:

 

 

接下來看看這個ASP.NET Core網站如何與Volume聯絡在一起。

 

首先下載aspnetcore-build映象:docker pull microsoft/dotnet:2.1-sdk

下載完映象之後,就需要建立容器和Volume了,不過在此之前先開啟命令列,進入ASP.NET Core專案原始碼的目錄:

 

然後執行下面的命令(Windows 10 Powershell):

docker run -it -p 8080:5001 -v ${PWD}:/app --workdir "/app" microsoft/dotnet /bin/bash

這句話裡-it參數列示進入互動模式

-p 8080:5001 表示把容器裡的5001埠對映給宿主的8080埠。

-v 表示建立volume

${PWD}是指宿主當前的目錄。

${PWD}:/app就是把容器裡的/app資料夾連線到了宿主系統裡的當前資料夾,而容器裡的/app目錄就是應用程式將要執行的位置。

 --workdir "/app"表示容器裡當前的工作目錄是/app。

然後使用microsoft/dotnet這個映象。

最後使用/bin/bash返回一個終端,以便讓我與容器裡進行互動。

 

執行命令後,Docker可能會有提示需要共享一個目錄,點選確認即可。

然後我就會進入Container了:

 

進入容器之後,我就可以執行dotnet restore, dotnet build等等命令了:

 

當然了,可以執行dotnet run:

 

然而這時候,我訪問本機(宿主)的localhost:8080,確無法顯式頁面。

首先為了簡便,先把HTTPS重定向相關的內容去掉。

然後要讓應用監聽任意地址的5001埠:

 

然後再次執行dotnet run。

隨後在宿主系統的瀏覽器開啟http://localhost:8080即可打這個ASP.NET Core的web應用了:

 

相關文章