你將發現這篇文章中涉及的東西很是具體,有的要求甚至至關苛刻且可能不具備通用性。這是由於部署歷來都是跟環境打交道,部署過程當中協做的組建太多,相互之間的交集不可能太大。可能惟一可以通用的是自動化部署的基本原則(只是這篇文章的基本原則):github
- 每一次自動化部署結束以後,應用程序都會有相同的初始狀態。
- 自動化部署的機器很是乾淨,只有相應的 Windows Server 系統和 .NET Framework。尤爲是,不會有 Visual Studio。
咱們須要公開一些基本的環境信息:shell
- 64-bit Windows Server 2008/2012/2012 R2或者 64-bit Windows 7/8/8.1
- 咱們的工程是使用 Microsoft Visual Studio 2013 開發的;
- .NET Framework 版本爲 4.5
- ASP.NET MVC 的版本爲 5.0.0
- Microsoft Build Tool 的版本爲 12.0
關於 MSBuild 這裏須要多說幾句。在 Visual Studio 2013 發佈以前,MSBuild 是隨 .NET Framework 一塊兒發佈的。這意味着咱們能夠不用安裝 Visual Studio 就能夠構建 .NET 應用程序。服務器
這是多麼美好的世界啊!所以,上一句話是假的。尤爲是當你構建 ASP.NET Web 應用程序的時候,你立刻就會遇到 「Cannot found … WebApplication.target」 的錯誤。若是你 StackOverflow 一下就能夠知道,咱們須要作的是安裝 Visual Studio 或者從另一臺安裝了 Visual Studio 的機器上將相關的文件拷貝出來。這真是——丟人的設計!Linux 的擁躉又有了發泄的空間。編輯器
因而微軟決定正視這個問題。從 Visual Studio 2013 開始,MSBuild 將與 Visual Studio 而不是.NET Framework 一塊兒發佈。這引來了一片罵聲。我不得不說,你們在生活中不論遇到什麼事情都要保持足夠的冷靜,每每先發脾氣的得不到任何的好處。事實是,因爲 .NET Framework 發佈的週期是相對較長的,所以微軟目前愈來愈傾向於使用 NuGet 進行類庫的發佈,這樣有助於削減 .NET Framework 基礎類庫的大小,並縮短基礎類庫的發佈週期。相應的 MSBuild 和 Visual Studio 的發佈週期也但願進行獨立的變化。MSBuild 將和 Visual Studio 保持發佈週期的一致性,並不意味這 MSBuild 依賴於 Visual Studio。所以咱們固然能夠下載 MSBuild 的獨立安裝包 Microsoft Build Tools,並在一臺沒有 Visual Studio 的服務器上進行自動化構建。函數
再次強調,若是幸運,你能夠直接運行這篇文章中的例子。可是你不要期望將這篇文章的腳本拷貝到你的工程就能夠正常工做。由於部署是一個因地制宜的任務,須要具體分析。你可能會遇到各類各樣的環境問題,可是我認爲最重要的仍是思路。工具
部署是什麼
簡單來講,部署就是 「構建(Build)」 –> 「拷貝」 –> 「配置」。那麼咱們就開始一個一個解決它。這一篇將着眼於構建。ui
編譯和構建應用程序 – 思路
如何構建應用程序呢?答案是先把須要的東西都拷貝過來,而後再用工具構建。好極了,咱們須要拷貝什麼東西呢?固然是先把源代碼拷貝過來。spa
┌────────────────┐ │ Src of MyApp │ └────────────────┘ |
光源代碼還不行,由於咱們的程序依賴於第三方庫(箭頭表明依賴關係)。命令行
┌────────────────┐ │ Dependent libs │ └────────────────┘ ↑ ┌────────────────┐ │ Src of MyApp │ └────────────────┘ |
例如,對於咱們構建的那個簡簡單單的 ASP.NET MVC 5 的應用程序,咱們就須要在構建以前下載它依賴的類庫:
- Microsoft.AspNet.Mvc 5.0.0
- Microsoft.AspNet.Razor 3.0.0
- Microsoft.AspNet.WebPages 3.0.0
- Microsoft.Web.Infrastructure 1.0.0.0
源代碼和依賴庫都拷貝完了,那麼接下來咱們就須要將構建工具也拷貝過來:
┌────────────────┐ │ Dependent libs │ └────────────────┘ ↑ ┌────────────────┐ ┌───────────────────┐ │ Src of MyApp │────→│Tools for compiling│ └────────────────┘ └───────────────────┘ |
對於咱們來講,構建的工具只有一個:
- MSBuild
現在工具,源代碼包羅萬象,咱們能夠開始編譯了。
安裝 MSBuild
若是你作實驗的機器上安裝了 Visual Studio 2013——Express 版本的也是能夠的——那麼你能夠跳過這一步,不然請下載 Microsoft Build Tools 並安裝。
下載應用程序的代碼
咱們的代碼是現成的,只須要從 git repository clone 下來就能夠了。你也能夠從這個地址 clone 到一個範例代碼,並轉換到相應的 commit。
git clone https://github.com/lxconan/MvcFromZero.git git reset --hard 340abb32433c99975bd6485f79db6ca077119477 |
好了,完成了,到目前爲止一切都是那麼的輕鬆愉快。
下載應用的依賴庫
咱們將使用 nuget 管理包的依賴。所以咱們首先要下載 NuGet 的命令行客戶端,能夠從這裏下載。
接下來的行爲都須要明確的目錄結構。爲了便於說明,咱們將創建以下的目錄結構。
MvcFromZero |- src | |- FromZero.App | |- packages | |- build |- tools |
其中,src 目錄存放 Solution 的源代碼,而 build 目錄存放自動化構建所需的各類工具和腳本。其中自動化構建須要的工具將放在 build/tools 目錄下。所以咱們也會將 nuget.exe 放在這個目錄下。
接下來咱們在 build 目錄下創建 deploy.ps1 腳本,咱們將在這個腳本中完成接下來的任務。咱們先來下載依賴的包。NuGet 的包管理是經過 package.config 文件進行的。須要指出的是 package.config也具備必定的層次關係。首先 Solution 級別的包信息存儲在兩個地方:
- 第一個是 Solution 目錄下的 .nuget/package.config 文件,這個文件中存儲的是非特定項目使用的包(若是並無這種類型的包,則該目錄不存在,或者該目錄下沒有任何文件);
- 第二個是 Solution 目錄下的 packages/repositories.config 文件,這個文件存儲了該解決方案下的每個工程的 packages.config 文件的路徑。
而 Solution 下的每個 Project 的包定義存儲在 Project 目錄下的 package.config 中。
爲了下載這些依賴的包是否須要人爲遍歷這些 config 文件呢?原來是,而從 nuget 2.7 開始,能夠直接支持 Solution 範圍內的包下載,因而額咱們就可使用以下的簡單函數完成包的下載了。
Function Install-SolutionPackages() { iex "$global_nugetPath restore $global_solutionFilePath" } |
其中,$global_nugetPath
是 nuget.exe 的路徑,而 $global_solutionFilePath
是工程文件(在這裏是 FromZero.App.csproj)的路徑。
接下來須要肯定的是構建工具的位置,咱們可使用註冊表查找 MSBuild 的位置的,因爲咱們使用了 2013 版本的 MSBuild(Toolset 的版本號爲 12.0),所以咱們的查找腳本爲:
Function Get-MsBuildPath() { $msBuildRegPath = "HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\12.0" $msBuildPathRegItem = Get-ItemProperty $msBuildRegPath -Name "MSBuildToolsPath" $msBuildPath = $msBuildPathRegItem.MsBuildToolsPath + "msbuild.exe" return $msBuildPath } |
上述兩步完成以後,就能夠編譯咱們的工程了:
Function Compile-Project() { iex -Command "& '$global_msBuildPath' $project_path" } |
你火燒眉毛的試驗了你的代碼,可是卻發現出了問題,MSBuild 報告沒法找到Microsoft.WebApplication.targets 文件。這是怎麼回事,咱們已經明明在 MSBuild 中安裝了Microsoft.WebApplication.targets 了啊?這是由於爲了保持和 Microsoft Visual Studio 2010 SP1 的工程的兼容性,Visual Studio 2012/2013 的工程默認將 $(VisualStudioVersion)
環境變量設置爲 10.0
。這樣,target 文件的查詢路徑就成了:
$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0 |
而不是:
$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v12.0 |
所以咱們須要修正這個環境變量。請使用文本編輯器打開 FromZero.App.csproj 文件,找到以下的定義:
<PropertyGroup> <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> <VSToolsPath Condition="'$(VSToolsPath)' == ''"> $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) </VSToolsPath> </PropertyGroup> |
將其中的 VisualStudioVersion
節替換爲:
<VisualStudioVersion>12.0</VisualStudioVersion> |
再次運行:祝賀你,你已經可以成功的下載全部的依賴,並完成工程的編譯了!在本文的結束,附上 deploy.ps1 到目前爲止的全部代碼:
$ErrorActionPreference = 'Stop' # Environment helpers ------------------------------------ Function Get-MsBuildPath() { $msBuildRegPath = "HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\12.0" $msBuildPathRegItem = Get-ItemProperty $msBuildRegPath -Name "MSBuildToolsPath" $msBuildPath = $msBuildPathRegItem.MsBuildToolsPath + "msbuild.exe" return $msBuildPath } # Environment variables ---------------------------------- $global_buildDirPath = Get-Location $global_msBuildPath = Get-MsBuildPath $global_solutionPath = "$global_buildDirPath\..\src" $global_solutionFilePath = "$global_solutionPath\src.sln" $global_nugetPath = "$global_buildDirPath\tools\nuget.exe" # Install nuget packages --------------------------------- Function Install-SolutionPackages() { iex "$global_nugetPath restore $global_solutionFilePath" } $project_path = $global_solutionPath + '\FromZero.App\FromZero.App.csproj' Function Compile-Project() { iex -Command "& '$global_msBuildPath' '$project_path'" } Install-SolutionPackages Compile-Project |