docker4dotnet #3 在macOS上使用Visual Studio Code和Docker開發asp.net core和mysql應用

北京的201個藍天發表於2016-07-28

.net猿遇到了小鯨魚,覺得越來越興奮。本來.net猿只是在透過家裡那田子窗看外面的世界,但是看著海峽對岸的蘋果園越來越茂盛,實在不想再去做一隻宅猿了。於是,.net猿決定搭上小鯨魚的渡輪到蘋果園去看看。

.net猿上了小鯨魚渡輪就先問了一個問題,蘋果園上有能用來編寫c#程式碼的和Visual Studio一樣強大的IDE麼?這時,天空閃過一道Gamma射線,艾瑞克神說,給你一個 Visual Studio Code,去玩吧。於是.net猿搭這小鯨魚的快船順利的抵達了蘋果山,開始了他的吃蘋果之旅。

… … 小編只能憋出來這麼多了,還是來乾貨吧。


今天,我們來看看如何在macOS上使用 Visual Studio Code 開發 Asp.net Core 應用,並使用Docker來進行開發除錯和部署。之前在使用 Visual Studio 的時候,我們看到了良好的整合性,IDE把所有的工具鏈全部配置好了,你要做的只是F5就可以了,今天我們來嘗試一下手工編寫Dockerfile和Docker-Compose檔案。另外,既然要開源,我們就徹底一點,這次我們不再使用sqlite或者sql server作為資料庫,而採用開源界最流行的mysql作為我們應用的後臺資料庫。

準備開發環境

首先我們需要下載和安裝幾個工具

1. Visual Studio Code 和 .Net Core

Visual Studio Code 是微軟為廣大開發人員提供的免費開源的跨平臺程式碼編輯器,和其它流行的程式碼編輯器,如:Sublime, Atom一樣,它非常小,執行速度快,同時通過各種外掛支援不同開發語言的編寫。不同的地方在於,VSC的外掛不僅僅提供靜態的語言高亮,自動語法檢測和完成功能外;還提供更加高階的編譯器服務支援,這使得VSC可以在一定程度上替代IDE的功能,進行程式碼的編譯,除錯和釋出操作。

d4d-3-vscode

下載地址:https://code.visualstudio.com
(同樣大家可以在公眾號中輸入d4dtools獲取最新版本的code安裝包,提供Windows/Mac/Linux不同版本)

Asp.net Core 是一個跨平臺的 asp.net 開發環境,可以通過以下地址下載macOS上的安裝包

d4d-3-netcore

下載地址:http://dot.net

注:如果你之前安裝過asp.net 5或者 rc版的.net core,需要在執行以上安裝命令之前先解除安裝,在d4dtools網盤中下載 dotnet-uninstall-pkgs.sh,執行即可。

2. Node.JS和NPM,以及 bower, gulp 和 grunt 等前端工具

Node.js是一個javascript的執行引擎,提供服務端的javascript執行能力,同時也包含了npm這個包管理器,可以用來安裝 bower, glup,grunt等前端工具。

d4d-3-node

下載地址:http://nodejs.org
(d4dtools中包含v4.4.7 LTS安裝包的Windows和Mac版本)

安裝完成後,讓通過以下命令安裝前端工具

npm install bower gulp grunt-cli -g

3. 安裝專案模版生成工具 yeoman 和 asp.net generator

YEOMAN是用來建立專案模版的工具,用慣了Visual Studio的開發人員一定都很喜歡新建專案的引導工具,選擇自己要用的專案型別就可以建立出一個可執行的基本專案框架,這讓啟動一個專案或者學習程式設計都變的非常容易。Yeman提供了同樣的功能。

d4d-3-yeoman

執行以下命令就可以完成yeoman的安裝

npm install yo -g

在yeoman中提供了不同的generator(模版生成器)來提供不同型別的專案的生成,為了能夠生成asp.net core應用,我們需要安裝aspnet generator

npm install generator-aspnet -g

安裝好以後就可以建立專案了

你也可以自己建立generator,參考 aspnet generator 的 github 原始碼來學習。
https://github.com/omnisharp/generator-aspnet

4. Docker for Mac

與 Docker for Windows 一樣,我們可以在macOS上安裝Docker for Mac來支援Docker環境的管理。

d4d-3-docker-for-mac

下載地址:https://www.docker.com/products/docker
(d4dtools網盤:Docker.dmg)

至此,我們的開發環境就準備完畢了。

建立asp.net core webapp

使用以上這些工具,我們就可以很順暢的建立應用程式了

1. 建立專案模版

首先建立一個應用目錄,原始碼目錄

mkdir aspnet-mysql
cd aspnet-mysql
mkdir src

然後進入src目錄使用yoman建立專案

cd src
yo aspnet

選擇 Web Application [without Membership and Authorization]作為專案型別,Bootstrap作為前端框架,並給出應用名稱aspnet-mysql

d4d-3-yo-aspnet

回車後,yoman建立專案中的程式碼檔案結構,並執行 bower install 完成所需要的javascript/css的安裝

然後執行以下命令,完成asp.net的nuget依賴包安裝

cd aspnet-mysql
dotnet restore

最後,鍵入以下命令開啟 Visual Studio Code

code .

這時,VSC會自動生成以下配置檔案,用於配置VSC中的開發除錯工具鏈

.vscode/launch.json
.vscode/task.json

現在,你就可以切換到除錯檢視,並點選執行按鈕開始除錯你的應用了,你也可以在程式碼中設定斷點,像在Visual Studio中一樣進行單步除錯,檢視變數數值的變化。

d4d-3-yo-vsc-debug

2. 建立mysql容器作為開發資料庫

資料庫的開發一般會要求我們先安裝一個資料庫引擎在自己的機器上,現在使用docker,我們可以在容器中執行一個資料庫引擎。這樣做有很多好處,1)自己的機器可以很乾淨,不用擔心各種程式之間互相沖突;2)資料庫隨用隨開,不用的時候就關掉,不必佔用資源;3)可以每次都用乾淨的資料庫進行除錯,不用操心恢復資料狀態;如果需要的話,也可以把容器中的資料卷內容同步到本機上。

要這樣做,首先你需要一臺容器化主機,可以參考本系列第二篇 《docker4dotnet #2 容器化主機》中的做法

這裡我使用了一臺執行在本地的vmwarefusion中的docker主機

d4d-3-dockervm

首先通過以下命令將docker命令重定向到這臺主機中

eval $(docker-machine env {machine-name})

執行以下命令啟動一臺mysql資料庫容器,建立一個叫做ef的資料,並將3306埠暴露給本地環境

docker run --name mysql-dev -e MYSQL_ROOT_PASSWORD=P2ssw0rd -e MYSQL_DATABASE=ef -p 3306:3306 -d mysql

引數說明:

  • name: 給容器起個名字叫做mysql-dev,這樣便於後邊管理用,如果不給名字的話docker會給一個隨機名字
  • -e: 配置容器的環境變數,這裡我配置了
    • MYSQL_ROOT_PASSWORD : root使用者密碼
    • MYSQL_DATABASE: 新資料庫名稱,mysql容器會按照要求建立一個ef為名稱的空資料庫
  • -p: 暴露埠,將3306埠暴露出來,便於管理

如果你本地沒有mysql的映象,docker會到docker hub去下載,如果已經有了映象那麼啟動真的是毫秒級的,啟動完成後你就可以使用管理工具連線到這個容器上,這裡我用的MySQL Workbench

d4d-3-mysqlbench

你可以看到 ef 資料庫已經建立好了。

3. 配置asp.net應用使用mysql作為Entity Framework資料來源

預設的asp.net 應用程式在Windows上使用sql server或者localdb作為資料來源,在非windows系統上使用的是sqlite。這裡,localdb和sqlite都只能作為開發除錯用途,如果需要投入生產就需要使用sql server,對應到開源產品,我們可以選用mysql作為sql server的替代品。在上一步中我們已經配置好了用於開發的mysql伺服器(容器),現在我們需要對應用程式進行配置,讓Entity Framework可以使用mysql作為資料來源。

這裡,我們使用的是由國內開發人員貢獻的開源庫,github地址如下:
https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql

首先在 project.json 檔案的 dependencies 配置節中加入以下引用:

"Pomelo.EntityFrameworkCore.MySql": "1.0.0-prerelease-20160726"

同時新增一個nuget.config配置檔案,並在裡面新增Pomelo的源地址,這主要是因為這個nuget庫現在還沒有正式釋出,釋出以後就不用進行這個配置了

<?xml version="1.0" encoding="utf-8"?>
<configuration>
 <packageSources>
 <add key="NuGet official package source" value="https://nuget.org/api/v2/" />
 <add key="PomeloMysql" value="https://www.myget.org/F/pomelo/api/v2/"/>
 </packageSources>
</configuration>

 

然後再次執行 dotnet restore,這次需要新增 –configfile nuget.config這個引數確保dotnet restore可以正確使用nuget源

dotnet restore --configfile nuget.config

4. 新增 MVC Model到專案中

現在我們就可以在專案中建立我們的實體類了,並且為了演示方便,我在還新增了一些示例資料。

程式碼檔案 https://github.com/ups216/aspnet-mysql/blob/master/src/aspnet-mysql/Models/Blog.cs

 

然後在starup.cs中的ConfigureServices方法中新增依賴注入程式碼

services.AddDbContext(options=>
 options.UseMySql(Configuration.GetConnectionString("Mysql")));

在Configure方法中呼叫SampleData.InitDB來建立示例資料

await SampleData.InitDB(app.ApplicationServices);

程式碼檔案:https://github.com/ups216/aspnet-mysql/blob/master/src/aspnet-mysql/Startup.cs

在 appsetting.json 中建立名為Mysql的連線字串

"ConnectionStrings": {
 "DefaultConnection": "Data Source=aspnetweb01.db",
 "Mysql": "Server={docker machine ip};database=ef;uid=root;pwd=P2ssw0rd;"
 }

程式碼檔案:https://github.com/ups216/aspnet-mysql/blob/master/src/aspnet-mysql/appsettings.json

確保 uid及pwd引數與docker run命令中的MYSQL_DATABASE,MYSQL_ROOT_PASSWORD一致
[docker machine ip]地址可以通過以下命令獲取

docker-machine ip

現在,再次使用VSC啟動應用進行除錯,你可以看到在mysql中的ef資料中Blogs和Users兩個表已經建立並且寫入了示例資料。

d4d-3-yo-vsc-debug-1

使用Docker打包釋出應用

以上我們已經完成了asp.net應用的建立,並且使用了一個執行在容器中的mysql進行開發除錯,現在我們需要將這個應用使用docker打包並執行在容器中。

1. 建立Dockerfile

使用yoman建立的應用本身就已經包含了一個Dockerfile,我們只需要進行簡單修改即可
檔案內容如下

FROM microsoft/dotnet:latest
COPY . /app
WORKDIR /app
RUN ["dotnet", "restore", "--configfile", "nuget.config"]
RUN ["dotnet", "build"]
EXPOSE 5000/tcp
ENTRYPOINT ["dotnet", "run", "--server.urls", "http://0.0.0.0:5000"]

程式碼連結:https://github.com/ups216/aspnet-mysql/blob/master/src/aspnet-mysql/Dockerfile

這個檔案很簡單,我們來看看它都做了些什麼:

  • FROM microsoft/dotnet:latest 告訴docker build使用microsoft/dotnet這個映象的最新版作為我們的base image
  • COPY . /app 將本機上Dockerfile所在目錄的所有檔案拷貝到容器的/app目錄中
  • WORKDIR /app 設定容器使用/app作為工作目錄,這樣後續的操作就都在這個目錄中進行
  • RUN dotnet restore 和 RUN dotnet build告訴docker build要執行dotnet restore和dotnet build兩個命令,同時使用nuget.config作為restore的配置檔案
  • EXPOSE 5000/tcp 暴露5000埠
  • ENTRYPOINT [“dotnet”, “run”, “–server.urls”, “http://0.0.0.0:5000”],設定容器入口為dotnet run命令,這個命令將啟動我們應用

2. 構建容器映象並執行容器

現在,我們就可以執行以下命令完成容器構建了

docker build -t {image name}.

其中 {image name} 你可以隨便起,我這裡用的是ups216/aspnet-mysql,這是我後面要上傳到docker hub上所用的名字

d4d-3-docker-build-1

d4d-3-docker-build-2

這裡在dotnet restore這一步會比較慢,因為需要下載所有的依賴包。

注:在日常開發中,你可以將先用常用包建立一個自己的base image,替換Dockerfile中的microsoft/dotnet,這樣就不用每次都重新下載包了。

現在鍵入docker images命令就可以看到我們新建立的image了

d4d-3-docker-images

執行

docker run --name aspnet-msyql-dev -p 5000:5000 ups216/aspnet-msyql

d4d-3-docker-run

你可以看到我們的容器現在也正確連線到了mysql容器的對外埠上了。在瀏覽器中輸入docker主機的ip地址:5000埠,我們的應用就完全在容器中跑起來了。

d4d-3-docker-run-app

在docker ps中看到的2個容器是這樣的

d4d-3-docker-ps

3. 生產部署打包

以上過程中我們已經將應用部署到了容器中,並且連線到另外一個容器中執行的mysql服務。但是,我們這個連線是通過mysql容器暴露給主機的埠來連線的,這樣做在開發過程中會比較方便,因為你可以容器的實用工具連線到mysql進行操作,但是如果要進行對外發布就不是個好主意了。

同時,我希望能夠將web應用和mysql容器一同部署,形成一個完整的應用部署包。這時,就需要藉助docker-compose來完成了。

首先,我們建立一個用於生產環境的配置檔案,appsettings.Production.json,內容如下:

{
 "ConnectionStrings": {
       "DefaultConnection": "Data Source=aspnetweb01.db",
       "Mysql": "Server=db;database=ef;uid=ef;pwd=P2ssw0rd;"
 },
 "Logging": {
      "IncludeScopes": false,
           "LogLevel": {
           "Default": "Debug",
           "System": "Information",
           "Microsoft": "Information"
           }
      }
 }

程式碼連結:https://github.com/ups216/aspnet-mysql/blob/master/src/aspnet-mysql/appsettings.Production.json

這裡我們主要修改了Mysql的連線字串,使用db作為資料庫,並使用ef作為連線使用者。

然後,我們建立一個 docker-compose.yml 檔案,內容如下:

version: '2'
 services:
   db:
     image: mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: P2ssw0rd
       MYSQL_DATABASE: ef
       MYSQL_USER: ef
       MYSQL_PASSWORD: P2ssw0rd

   web:
     build: .
     depends_on:
       - db
     links:
       - db
     ports:
       - "5000:5000"
     restart: always
     environment:
     ASPNETCORE_ENVIRONMENT: Production

裡面的內容基本上可以從字面意思讀懂,這裡主要建立了db和web兩個容器,web容器依賴db容器,並通過db這個名字連結過去,同時設定asp.net core的environment環境變數為Production。

對應以上我們在appsettings.Production.json檔案中做的修改,你就可以理解我們通過Production這個環境變數配置我們的應用去到一個叫做db的mysql伺服器上鍊接名為ef的資料庫,並且使用ef作為使用者名稱。

現在,你只需要執行以下這一個命令就可以完成這兩個容器的啟動了

docker-compose up

d4d-3-docker-compose-up

以上程式碼都已經發布到我的github上,地址如下:

https://github.com/ups216/aspnet-mysql/

如果你按照本文的第一部分安裝了所有工具,那麼你應該可以直接用行docker-compose up來啟動這個應用;以下我錄製了一段簡單的視訊(3分鐘)來演示這個過程。

 

相關文章:


 

請關注微信公眾號 【devopshub】,獲取更多關於DevOps研發運維一體化的資訊

qrcode_for_gh_b7c158df1fd1_430

相關文章