1. 程式人生 > >Linux 上安裝Docker 並部署netcor2.1

Linux 上安裝Docker 並部署netcor2.1

容器,顧名思義是用來存放並容納東西的器皿;

而容器技術伴著Docker的興起也漸漸的映入大家的眼簾,它是一個抽象的概念,同時也是默默存在世上多年的技術,不僅能使應用程式間完全的隔離,而且還能在共享底層系統資源的同時發揮它最大的優勢。相比於虛擬機器來說,同一伺服器它可以創建出兩倍的例項,這樣一來,不僅節省了系統開銷,而且利用率和效能也得到了提升,何樂而不為。最重要的一點是還幫助開發人員實現了“一次構建,到處執行”的理想!

那麼Docker又是什麼呢?

  • Docker是基於Go語言開發並開源的容器引擎

  • Docker將應用軟體執行時所需的一切都打包成互相隔離的容器

  • Docker可以自動執行並配置開發/線上環境,快速構建,測試和運行復雜的多容器應用程式

  • 對擁有數千個節點或容器的應用程式,Docker也能快速的擴充套件和調配

  • 可以執行在主流的Linux系統,Mac以及Windows上,並且保證無論軟體在哪裡部署,都能正常執行並得到相同的結果

相關概念介紹

  • Image映象和Container容器:你可以把兩者理解為類和例項物件,或者是ISO系統映象和虛擬機器的關係。不同的Image所包含的軟體或者環境是不同的,但是你可以使用Dockerfile(docker特有語法規則所建立的檔案)進行管理。而Container則是以Image作為模板,可以獨立執行的微型系統,一個Image可以創建出來多個Container容器的例項

  • Registry:Docker Hub映象倉庫,為每個人提供龐大的映象資源進行拉取和使用

  • Dockerfile:是一個將映象命令組合在一起的檔案,用於Image的自動構建

正文

系統環境

宿主機:Windows 10 專業版

Linux伺服器: Ubuntu 17.04 (GNU/Linux 4.10.0-28-generic x86_64),從16.10版本升級的,由Hyper-V管理

軟體環境

開發工具:Visual Studio 2017 15.3(.NET Core 2.0)

遠端管理工具:Putty,基於SSH,操作簡單的遠端命令控制,省得你把命令給敲錯咯

SFTP客戶端:WinScp,處理Linux和Windows間的檔案傳輸

容器:Docker 17.06.0-CE

一、安裝Docker

a)、設定Docker倉庫

1、按慣例,首先更新Ubuntu的包索引

$ sudo apt-get update

2、讓伺服器可以使用Https更新倉庫

$ sudo apt-get install apt-transport-https ca-certificates curl software-properties-common

3、新增Docker官方的金鑰對,如果沒問題,會返回“OK”

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

4、校驗金鑰(9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88)是否和官方一致

$ sudo apt-key fingerprint 0EBFCD88

5、設定官方穩定版的倉庫來源

$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

b)、安裝Docker

1、再次更新下包索引,因為剛才加了Docker倉庫,確保是否命中了Docker源

$ sudo apt-get update

2、安裝最新版本的Docker-CE社群版

$ sudo apt-get install docker-ce

3、需要安裝其他版本的請使用以下命令

$ sudo apt-get install docker-ce=1.13

4、檢視是否安裝成功

$ docker version

5、試著執行一個測試映象,萬能的Hello World!

$ sudo docker run hello-world

二、.NetCore的Docker配置

準備工作:首先記錄接下來可能會用到的幾個常用命令

複製程式碼
sudo docker pull microsoft/dotnet    //從docker倉庫拉取一個名稱為“microsoft/dotnet”的映象

sudo docker build light    //構建一個名稱為light的容器

sudo docker run hello-world    //執行hello-world容器

sudo docker images    //檢視所有映象

sudo docker rmi 63sf86332e    //刪除一個imageid的映象

sudo docker rmi $(docker images -q)    //刪除所有映象

sudo docker ps -a    //檢視所有容器

sudo docker rm 6f0c67de4b72    //刪除一個containerid的容器

sudo docker rm $(sudo docker ps -a -q)   //刪除所有容器
複製程式碼

1、拉取dotnet-sdk的最新映象,速度慢的話請自行搜尋daocloud docker hub加速。

sudo docker pull microsoft/dotnet:latest

完成之後檢視一下映象

sudo docker images

2、進入到這個映象,檢視版本沒問題後建立一個控制檯程式,然後執行並檢視結果

複製程式碼
sudo docker run -it  microsoft/dotnet  //每次run,都會重新構造出新的互不影響的容器,請自行檢視

dotnet --version

mkdir test

cd test

dotnet new
複製程式碼

dotnet new console

dotnet run    //.NetCore2.0已經將dotnet restore變成了隱式命令,需要的時候會自動執行

說明:使用Ctrl+D快捷鍵或者鍵入exit命令來退出命令

三、升級專案到.NetCore2.0,併發布

1、分別修改類庫和Web的專案檔案,升級到.Net Core 2.0和.Net Standard 2.0,其中包括Nuget上的一些元件,或者直接通過右鍵專案->屬性->目標框架進行修改,同時修改Program.cs和Startup.cs檔案為2.0預設的方式,完成後他們的樣子是醬紫的,是不是很簡潔明瞭。

類庫的csproj專案檔案:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>
</Project>

Web的csproj專案檔案

複製程式碼
<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <RuntimeIdentifiers>win10-x64;ubuntu.16.10-x64;ubuntu.16.04-x64</RuntimeIdentifiers>
   <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Session" Version="2.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.0" />
   <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.ViewCompilation" Version="2.0.0" PrivateAssets="All" /> </ItemGroup> <ItemGroup> <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\Light.Common\Light.Common.csproj" /> <ProjectReference Include="..\Light.Model\Light.Model.csproj" /> </ItemGroup> </Project>
複製程式碼

簡潔的Program.cs

複製程式碼
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;

namespace Light.Web
{
    public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .Build();
    }
}
複製程式碼

下面是我的Startup檔案的相關配置項

複製程式碼
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Light.Web.DBContext;
using Microsoft.EntityFrameworkCore;
using Light.Web.Models;

namespace Light.Web
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<LightContext>(m =>
            {
                m.UseSqlServer(Configuration.GetConnectionString("LightContextConnection"));
            });
            services.AddSession(m =>
            {
                m.IdleTimeout = TimeSpan.FromHours(1);
            });
            services.AddMvc(m =>
            {
                m.Filters.Add(typeof(LightActionFilter));
                m.Filters.Add(new LightExceptionFilter());
            });
            var serviceProvider = services.BuildServiceProvider();
            var dbContext = serviceProvider.GetService<LightContext>();
            LightContextSeed.SeedAsync(dbContext).Wait();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();
            app.UseSession();
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}
複製程式碼

微軟官方的升級嚮導,供大家參考:https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/

2、使用cli命令釋出專案,這時可以不用指定執行時標識,直接釋出,因為專案不是執行在伺服器(Windows或Linux)上的。

dotnet publish -c Release -o ../Publish

四、使用Docker進行部署

1、使用Winscp登陸到伺服器上,並將釋出之後的資料夾publish上傳到伺服器上

2、建立Dockerfile檔案,並將其配置成以下內容

FROM microsoft/dotnet
WORKDIR /app
COPY ./publish .
ENTRYPOINT ["dotnet", "Light.Web.dll"]

3、切換到Dockerfile所在的目錄下,並執行構建命令,成功之後會有下圖的提示

sudo docker build -t lightweb .  //注意後邊還有一個點呢

4、執行剛才構建成功,名字為lightweb的容器,直接繫結伺服器的80埠

sudo docker run -p 80:80 -e "ASPNETCORE_URLS=http://+:80" lightweb

執行成功之後是這樣的(請暫時忽略Warning),表示該容器內的程式正在使用80埠監聽著.......

5、試著用IP訪問一下,不知道自己IP的請使用ifconfig命令進行檢視

 

最後

在看到最後一張圖的時候,其實自己心裡還是挺激動的;雖然中間遇到一些差錯,比如專案檔案中的MvcRazorCompileOnPublish節點,釋出成ubuntu時需要改成false,或者直接刪掉,再者是圖片的名稱字尾是大寫,但是我程式裡邊寫的是小寫,釋出之後圖片不顯示,是因為Linux是嚴格區分大小寫的。囧~另外提醒一下,釋出到IIS上時,請及時更新AspNetCoreModule模組為最新的DotNetCore.2.0.0-WindowsHosting.exe