1. 程式人生 > >.NET Core容器化開發系列(一)——Docker裏面跑個.NET Core

.NET Core容器化開發系列(一)——Docker裏面跑個.NET Core

開源鏡像站 final 輸出 快速 image 測試版本 storage gem targe

前言

博客園中已經有很多如何在Docker裏面運行ASP.NET Core的介紹了。本篇主要介紹一些細節,幫助初學的朋友更加深入地理解如何在Docker中運行ASP.NET Core。


技術分享圖片

安裝Docker

Docker現支持在主流Linux、Windows和macOS上安裝,官方的安裝文檔請參考docker docs。鑒於國內的網絡環境,建議通過國內大廠/高校提供的鏡像站快速安裝,比如 阿裏巴巴開源鏡像站,Ubuntu和Centos7上的安裝方式如下:


Ubuntu 14.04 16.04 (使用apt-get進行安裝)

# step 1: 安裝必要的一些系統工具
sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# step 2: 安裝GPG證書
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# Step 3: 寫入軟件源信息
sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# Step 4: 更新並安裝 Docker-CE
sudo apt-get -y update
sudo apt-get -y install docker-ce

# 安裝指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# apt-cache madison docker-ce
#   docker-ce | 17.03.1~ce-0~ubuntu-xenial | http://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
#   docker-ce | 17.03.0~ce-0~ubuntu-xenial | http://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
# Step 2: 安裝指定版本的Docker-CE: (VERSION 例如上面的 17.03.1~ce-0~ubuntu-xenial)
# sudo apt-get -y install docker-ce=[VERSION]

CentOS 7 (使用yum進行安裝)

# step 1: 安裝必要的一些系統工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加軟件源信息
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3: 更新並安裝 Docker-CE
sudo yum makecache fast
sudo yum -y install docker-ce
# Step 4: 開啟Docker服務
sudo systemctl enable docker && systemctl start docker

# 註意:
# 官方軟件源默認啟用了最新的軟件,您可以通過編輯軟件源的方式獲取各個版本的軟件包。例如官方並沒有將測試版本的軟件源置為可用,你可以通過以下方式開啟。同理可以開啟各種測試版本等。
# vim /etc/yum.repos.d/docker-ce.repo
#   將 [docker-ce-test] 下方的 enabled=0 修改為 enabled=1
#
# 安裝指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# yum list docker-ce.x86_64 --showduplicates | sort -r
#   Loading mirror speeds from cached hostfile
#   Loaded plugins: branch, fastestmirror, langpacks
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            docker-ce-stable
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            @docker-ce-stable
#   docker-ce.x86_64            17.03.0.ce-1.el7.centos            docker-ce-stable
#   Available Packages
# Step2 : 安裝指定版本的Docker-CE: (VERSION 例如上面的 17.03.0.ce.1-1.el7.centos)
# sudo yum -y install docker-ce-[VERSION]

以下我的實驗在Centos7中進行,其他系統基本類似。

安裝完成後,可以看到最新Docker版本為18.09(2018年12月27日)

技術分享圖片


效果0X01

既然Docker安裝好了,也正常運行起來了,我們第一件事兒做的就是運行一下Demo,看看是個什麽效果,微軟將dotnet的Docker鏡像都托管在Docker Hub上,我們可以打開Docker Hub的官方網站:https://hub.docker.com 並直接搜索dotnet,找到microsoft/dotnet即可。

根據Wiki提示,我們使用如下命令運行第一個ASP.NET Core的Demo:

docker run -it --rm -p 8000:80 --name aspnetcore_sample microsoft/dotnet-samples:aspnetapp

運行後輸出:

[root@singleCentos7 ~]# docker run -it --rm -p 8000:80 --name aspnetcore_sample microsoft/dotnet-samples:aspnetapp
Unable to find image 'microsoft/dotnet-samples:aspnetapp' locally
aspnetapp: Pulling from microsoft/dotnet-samples
a5a6f2f73cd8: Pull complete 
1e6f560accc2: Pull complete 
8176b77dc10d: Pull complete 
e21dd5015bb0: Pull complete 
10a7ec297783: Pull complete 
52c4b3af04fb: Pull complete 
Digest: sha256:de388b1ced92eadb906f806d0253d93c76cb92b0814798e7441c014b9645a32c
Status: Downloaded newer image for microsoft/dotnet-samples:aspnetapp
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
      No XML encryptor configured. Key {024f9978-2fea-4d8e-818a-b9a378553244} may be persisted to storage in unencrypted form.
Hosting environment: Production
Content root path: /app
Now listening on: http://[::]:80
Application started. Press Ctrl+C to shut down.


簡單解釋一下命令中幾個常見的參數:

-it 開啟一個交互窗口,也急運行docker後,處於docker的交互式輸入輸出頁面

--rm 當從運行的容器中退出(ctrl+c)時,刪除鏡像殘留信息及數據

-p 端口映射,將宿主機端口映射到容器內端口

--name 給容器起個名字,如不設置該項,容器名稱將有docker服務隨機設定

最後是鏡像的地址以及tag


運行該段命令後:

首先查詢宿主機本地是否存在microsoft/dotnet-samples:aspnetapp鏡像

如不存在,則從遠端拉取鏡像

拉取成功後,運行指定命令,將Demo服務運行起來


此時我們在局域網的任意一臺電腦瀏覽器中輸入http://[宿主機IP]:8000 即可打開容器運行的demo

技術分享圖片

效果0X02

看完官方的Demo,接下來我們自制一個DemoV2 。該思路采用將Docker容器轉制為鏡像的辦法,因該方法擴展性不強,不適合重復使用,因此不被推薦,但其中的部分思路非常適合借鑒學習:

docker run -it --rm --name dotnet_sdk microsoft/dotnet:sdk

技術分享圖片

接下來我們在tmp目錄下新建一個ASP.NET Core MVC項目,並發布該項目都/app目錄下

技術分享圖片


此時我們進入/app目錄後,執行命令,即可看到demo1已經能在容器中正常運行:

cd /app && dotnet demo1.dll

接下來我們使用docker commit命令將當期容器轉制為鏡像,以便於我們重復使用。

首先,新開一個宿主機終端,並在終端中查看當期運行的容器:

docker ps

技術分享圖片

可以發現名稱為dotnet_sdk的容器,其容器Id為9bc83a01a0d1,此時執行如下命令:

docker commit 9bc83a01a0d1 mydemo:v1

即可將指定容器保存為名稱為mydemo的鏡像,執行docker images查看:

技術分享圖片

包含我們demo程序的鏡像就已經保存下來了,接下來我們可以直接運行該鏡像查看效果:

docker run -it --rm -p 8001:80 --name ggg mydemo:v1 sh -c "cd /app && dotnet demo1.dll"

技術分享圖片

打開瀏覽器訪問效果:

技術分享圖片


效果0x03

接下來我們用最常見也是最合適的方式制作我們的.NET Core MVC鏡像---Dockerfile

如果我們希望在Linux下直接開始.NET Core的代碼編寫,首先就必須要安裝平臺相關的.Net Core SDK,安裝完成後,才可以使用dotnet 的相關指令創建、編譯、發布項目。此時我們可以在Docker下采取更“雞賊”一些的辦法:

首先,我們運行一個.Net Sdk的容器,並進入交互式界面:

docker run -it --rm --name dotnet_sdk -v /tmp/src:/tmp/src  microsoft/dotnet:sdk

運行.Net Core最新的SDK,並將宿主機/tmp/src 文件夾掛在到容器/tmp/src下面,而後我們在這個文件夾的文件都不會因容器銷毀二丟失。

技術分享圖片

查看容器中dotnet版本信息,並在容器的/tmp/src文件夾下創建新的ASP.NET Core MVC項目:

cd /tmp/src
dotnet new mvc -n mydemo

技術分享圖片


此時可以退出當前容器了,接下來進入的是Docker的打包步驟。

雖然這種做法有點“畫蛇添足”,但在某些時刻還是挺有用的,比如系統中存在老版本的.NET Core SDK,安裝新版本的SDK可能會產生未知的問題,此時在Docker裏面瞎玩,隨便搞都沒問題,棒呆!


同時有必要再強調一下,Docker從17.05版本開始支持“多階段構建(multi-stages builds)”,而大多數幹凈的Linux操作系統在直接使用系統包管理器安裝docker時安裝的是13.1的版本Docker,是不支持該特性的。

下面介紹的模式是分層結構的構建方式。

在宿主機/tmp/src/mydemo下新建Dockerfile文件,輸入以下內容:

FROM microsoft/dotnet:2.2-runtime AS base
WORKDIR /app
EXPOSE 80

FROM microsoft/dotnet:2.2-sdk AS publish
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "mydemo.dll"]


該腳本一共分3次,第一次定義了基礎鏡像,並設置/app為基礎工作目錄,告知外部80為開放端口

第二次,將當期目錄下的所有文件發送給Docker服務,執行發布過程,將發布輸出到/app文件夾下

第三次,采用第一次的鏡像基礎作為當期鏡像,並將第二次發布輸出拷貝到當前基礎工作目錄/app

最後設置工作入口,當鏡像運行時,執行dotnet mydemo.dll

技術分享圖片

通過docker images命令可以看到剛剛打包出的鏡像

技術分享圖片


接下來我們嘗試將鏡像運行起來:

docker run -it --name mydemo -p 8002:80 mydemo:v1

技術分享圖片

技術分享圖片

成功!



這次隨筆主要介紹了在Docker裏面如何運行一個.NET Core項目的Demo,建議大家在學習Docker時,對如何書寫Dockerfile多下點功夫,理解裏面的基礎命令關鍵詞。


.NET Core容器化開發系列(一)——Docker裏面跑個.NET Core