Try .NET Core

.NET Coreを動かした、試した記録を書き残します。

ASP.NET Coreサンプルアプリ「MusicStore」を動かす

開発環境が一通り整いましたので、実際に開発の方を試したくなります。

テンプレートのコードを眺めると、MVCフレームワークを1つ2つ齧ったことがあれば、ざっくりとした挙動は想像できます。

しかし、もう少し、情報が欲しい。

Web案件では主にPHPで、業務系案件は古臭いWebフォームを扱うばかりだった私は、ASP.NET MVCというMicrosoftご謹製フレームワークについて、全く知識がありません。

なにか手頃な、そこそこ主だった実装があるサンプルコードが無いかと探したら、「MusicStore」というサンプルに行き着きました。

aspnet/MusicStore Sample MusicStore application that uses MVC and Entity Framework.
f:id:try_dot_net_core:20161207220252j:plain

音楽ショップのサンプルということで、ユーザー認証やカート機能など、実践的なコードが読めそうです!
早速ソースを頂いて、Visual Studioで開いてみます。

実行してみる

README.mdに実行の仕方が書いてあるんですが、

If you have Visual Studio 2015
   i. Open MusicStore.sln in Visual Studio 2015 and run the individual applications on IIS Express.

やー。ずいぶん、ざっくりっすね~。
DBの記述が見当たりません。
要らないってことも無いよね、と思いつつ。

パッケージ復元とビルドは、本記事記述時最新の2016年11月24日コミットの状態で、何事もなく通りました。

別環境でパッケージ復元にハマったことがありましたが、その際はNugetパッケージの管理画面でプレリリースを含めるチェックボックスを入れて検索することで、無事にインストール出来ました。
f:id:try_dot_net_core:20161208215916j:plain

README.md上では/src/MusicStore/のパスが散見されるので、これがメインプロジェクトなのでしょう。
f:id:try_dot_net_core:20161208215120j:plain

実行すると。
f:id:try_dot_net_core:20161208220325j:plain
例外ですねー...。

例外を解析する

詳細表示すると、InnerExceptionのStackTraceに発生位置がありました。
f:id:try_dot_net_core:20161208221055j:plain
Models\SampleData.cs:行 26とな。

該当箇所はこんな感じです。
f:id:try_dot_net_core:20161208221854j:plain
EnsureCreateAsyncですって。非同期で確実に生成するぜ、と。
その後に続くロジックが、InsertTestDataCreateAdminUserとのことですんで、どうやらDBインスタンスを新規作成してるようですね。

なにか設定ファイルにヒントが無いかと、プロジェクト内をみてみます。
config.jsonというファイルに、DBの接続文字列っぽいのがありました。
f:id:try_dot_net_core:20161208222324j:plain

中身はこちら

{
  "AppSettings": {
    "SiteTitle": "ASP.NET MVC Music Store",
    "CacheDbResults": true
  },
  "DefaultAdminUsername": "Administrator@test.com",
  "DefaultAdminPassword": "YouShouldChangeThisPassword1!",
  "Data": {
    "DefaultConnection": {
      // Use a shared (and running) LocalDB database when executing in IIS e.g.
      // "Server=(localdb)\\.\\IIS_DB;Database=MusicStore;Trusted_Connection=False;MultipleActiveResultSets=true;User ID=iis_login;Password=********"
      "ConnectionString": "Server=(localdb)\\MSSQLLocalDB;Database=MusicStore;Trusted_Connection=True;MultipleActiveResultSets=true;Connect Timeout=30;"
    }
  }
}

どうも、ローカルのSQL Server上のMusicStoreというインスタンスに繋ごうとしてる?
お望みどおり(?)、SQL Serverを起動して、MusicStoreインスタンスを作ります。
インスタンスだけの状態で、テーブルもデータも空っぽです。
f:id:try_dot_net_core:20161208223001j:plain

config.jsonの接続文字列を書き換えて、ローカルSQL Serverに繋がるようにします。

{
  "AppSettings": {
    "SiteTitle": "ASP.NET MVC Music Store",
    "CacheDbResults": true
  },
  "DefaultAdminUsername": "Administrator@test.com",
  "DefaultAdminPassword": "YouShouldChangeThisPassword1!",
  "Data": {
    "DefaultConnection": {
      // Use a shared (and running) LocalDB database when executing in IIS e.g.
      // "Server=(localdb)\\.\\IIS_DB;Database=MusicStore;Trusted_Connection=False;MultipleActiveResultSets=true;User ID=iis_login;Password=********"
      "ConnectionString": "Server=localhost;Database=MusicStore;Trusted_Connection=True;MultipleActiveResultSets=true;Connect Timeout=30;User ID=[ユーザーID];Password=[パスワード]"
    }
  }
}

jsonなのに、コメントアウト出来るんですね。
便利だけど、いいのかなMSさん...(困惑)

無事に動いた!

あらためて、Visual Studioから実行すると... f:id:try_dot_net_core:20161208223959j:plain
きました!
トップにMen at Workを持ってくるあたり、趣味が合いそうです。

ユーザー登録やログイン、カート処理など、一通り動くようです。
f:id:try_dot_net_core:20161208224449j:plain

今後はこのソースを研究しようと思います!

.NET Core ver1.0.1プロジェクトを、ver1.1.0に上げるには?

現在、Visual Studio 2015 Update3 で作られる ASP.NET Core テンプレートプロジェクトの.NET Coreバージョンは 1.0.1 です。

これまでで linux / macともに .NET Core ver1.0.1 / 1.1.0 の二つをインストールしましたので、プロジェクトのバージョンを上げてみます。

.NET Coreのバージョン確認

ASP.NET Coreプロジェクトの.NET Coreバージョンは、project.jsonに書かれています。
テンプレート状態はこちら。

{
  "dependencies": {
    "Microsoft.NETCore.App": {
      "version": "1.0.1",
      "type": "platform"
    },
    "Microsoft.AspNetCore.Diagnostics": "1.0.0",
    "Microsoft.AspNetCore.Mvc": "1.0.1",
    "Microsoft.AspNetCore.Razor.Tools": {
      "version": "1.0.0-preview2-final",
      "type": "build"
    },
    "Microsoft.AspNetCore.Routing": "1.0.1",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
    "Microsoft.AspNetCore.StaticFiles": "1.0.0",
    "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
    "Microsoft.Extensions.Configuration.Json": "1.0.0",
    "Microsoft.Extensions.Logging": "1.0.0",
    "Microsoft.Extensions.Logging.Console": "1.0.0",
    "Microsoft.Extensions.Logging.Debug": "1.0.0",
    "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
    "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0"
  },

  "tools": {
    "BundlerMinifier.Core": "2.0.238",
    "Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final",
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final"
  },

  "frameworks": {
    "netcoreapp1.0": {
      "imports": [
        "dotnet5.6",
        "portable-net45+win8"
      ]
    }
  },

  "buildOptions": {
    "emitEntryPoint": true,
    "preserveCompilationContext": true
  },

  "runtimeOptions": {
    "configProperties": {
      "System.GC.Server": true
    }
  },

  "publishOptions": {
    "include": [
      "wwwroot",
      "**/*.cshtml",
      "appsettings.json",
      "web.config"
    ]
  },

  "scripts": {
    "prepublish": [ "bower install", "dotnet bundle" ],
    "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
  }
}

また、プロジェクトをビルドした際に、バージョン表記が出力されます。

[root@centos7 WebApplication1]# dotnet build
Project WebApplication1 (.NETCoreApp,Version=v1.0) will be compiled because expected outputs are missing
Compiling WebApplication1 for .NETCoreApp,Version=v1.0    <--ココ

Compilation succeeded.
    0 Warning(s)
    0 Error(s)

Time elapsed 00:00:02.5954545


バージョンを書き換える

まずはframeworksセクションから。
netcoreapp1.0->netcoreapp1.1に書き換えます。
f:id:try_dot_net_core:20161207113209j:plain

書き換えてから保存すると、その都度バッケージの復元処理が走ります。
f:id:try_dot_net_core:20161207113306j:plain

書き換えたあと、ビルドが通らなくなることがあります。
複数項目を一括で書き換えたあとにビルドが通らなくなった場合、どの項目が原因なのかが分からなくなるため、書き換える都度ビルドします。
f:id:try_dot_net_core:20161207120537j:plain

次にdependenciesセクション。
依存dllのバージョンですね。
Visual Studio 2015 Update3では、バージョン表記を一旦消してからCtrl + SpaceするとIntelliSenceが候補を挙げてくれます。
f:id:try_dot_net_core:20161207112439j:plain



このようにして書き換えた結果が、下記になります。

{
  "dependencies": {
    "Microsoft.NETCore.App": {
      "version": "1.1.0",
      "type": "platform"
    },
    "Microsoft.AspNetCore.Diagnostics": "1.1.0",
    "Microsoft.AspNetCore.Mvc": "1.1.0",
    "Microsoft.AspNetCore.Razor.Tools": {
      "version": "1.1.0-preview4-final",
      "type": "build"
    },
    "Microsoft.AspNetCore.Routing": "1.1.0",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
    "Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
    "Microsoft.AspNetCore.StaticFiles": "1.1.0",
    "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0",
    "Microsoft.Extensions.Configuration.Json": "1.1.0",
    "Microsoft.Extensions.Logging": "1.1.0",
    "Microsoft.Extensions.Logging.Console": "1.1.0",
    "Microsoft.Extensions.Logging.Debug": "1.1.0",
    "Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0",
    "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.1.0"
  },

  "tools": {
    "BundlerMinifier.Core": "2.0.238",
    "Microsoft.AspNetCore.Razor.Tools": "1.1.0-preview4-final",
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.1.0-preview4-final"
  },

  "frameworks": {
    "netcoreapp1.1": {
      "imports": [
        "dotnet5.6",
        "portable-net45+win8"
      ]
    }
  },

  "buildOptions": {
    "emitEntryPoint": true,
    "preserveCompilationContext": true
  },

  "runtimeOptions": {
    "configProperties": {
      "System.GC.Server": true
    }
  },

  "publishOptions": {
    "include": [
      "wwwroot",
      "**/*.cshtml",
      "appsettings.json",
      "web.config"
    ]
  },

  "scripts": {
    "prepublish": [ "bower install", "dotnet bundle" ],
    "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
  }
}

差分はこんな感じ。
f:id:try_dot_net_core:20161207115453j:plain

ビルド時のバージョン表記も、変わってますね。

[root@centos7 WebApplication1]# dotnet build
Project WebApplication1 (.NETCoreApp,Version=v1.1) will be compiled because expected outputs are missing
Compiling WebApplication1 for .NETCoreApp,Version=v1.1

Compilation succeeded.
    0 Warning(s)
    0 Error(s)

Time elapsed 00:00:12.9917026



今回分のソースコードはこちら。
github.com

Visual Studio for Mac は .NET Core の夢を見るか?

macの.NET Coreをセットアップしたところなので。

macの.NET関連技術について、ちょろっと試します。

Visual Studio for Macは、ASP.NET Coreプロジェクトを編集できるの?

できませんでした...。
こんなエラーが出ます。
f:id:try_dot_net_core:20161206013230j:plain

Visual Studio for Macは、*.xproj形式のプロジェクト定義ファイルを読めません。
今後対応が入るかどうかは、分かりません。

こちらに詳しいですが、Visual Studio 2017から、.NET Coreプロジェクトの定義ファイル形式が、現在の*.xproj形式から旧来.NET Frameworkプロジェクトの*.csproj形式に戻るそうです。

参考:
Visual Studio for Macの.NET Coreサポートの実装について
MSBuild ベースの .NET Core Tools の「アルファ版」を発表


Visual Studio for Macは、Xamarin build hostになれるの?

なれます!

f:id:try_dot_net_core:20161206013956j:plain こちらの接続先macには、Xamarin Studioは入っておりません。
裏にうっすら見えていますが、Storyboardも開けています。(相変わらず激重ですが)

今まで、build hostにはXamarin Studio Community Editionを入れてましたが。
Xamarin本家のページを見る限り、今後はVisual Studio for Macに置き換えていくようですね。

というよりむしろ。
Visual Studio for Macは、Xamarin Studioのお色直し版、ですね。


macOS10.11で、ASP.NET Coreアプリを動かす

.NET Coreは mac でも動くとのこと。
ウチではWindowsLinuxが主ですが、mac使いのプログラマも多いですよね。
macでの.NET Coreは、さて、どんなものか。
ざっと試してみます。

インストール手順は、おおむね公式ドキュメントに準じます。

Homebrewをインストール

どうやら、最新のopensslが要るんだぜ、と。
Homebrewというヤツを入れるのが手っ取り早いぜ、とのこと。

どうやら、yumのようなパッケージ管理システムのようです。
いれます。

mac-05rw:~ 05rw$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
==> This script will install:
/usr/local/bin/brew
/usr/local/share/doc/homebrew
 --- 中略 ---
- Run `brew help` to get started
- Further documentation: 
    https://git.io/brew-docs
mac-05rw:~ 05rw$ 


opensslをインストール

続いてご指名のopensslを、貰ってきます。

mac-05rw:~ 05rw$ brew install openssl
==> Downloading https://homebrew.bintray.com/bottles/openssl-1.0.2j.el_capitan.b
######################################################################## 100.0%
==> Pouring openssl-1.0.2j.el_capitan.bottle.tar.gz
 --- 中略 ---
    CPPFLAGS: -I/usr/local/opt/openssl/include

==> Summary
🍺  /usr/local/Cellar/openssl/1.0.2j: 1,695 files, 12M

なんか旨そうなの見えてますけど。

リンクも張りますよ。

mac-05rw:~ 05rw$ mkdir -p /usr/local/lib
mac-05rw:~ 05rw$ ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/
mac-05rw:~ 05rw$ ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/


.NET Core SDKをインストール

公式バイナリ配布ページからtar玉を、ver1.1.0ver1.0.1の二つを貰ってきます。
f:id:try_dot_net_core:20161205185058j:plain

解凍先フォルダをバージョンごとに

  1. ver1.1.0用 - ./dotnet
  2. ver1.0.1用 - ./dotnet101

のように二つ作り、それぞれを解凍します。

mac-05rw:~ 05rw$ cd Downloads/
mac-05rw:Downloads 05rw$ ls -alF
total 426504
drwx------+  5 05rw  staff        170 12  5 18:29 ./
drwxr-xr-x+ 13 05rw  staff        442 12  5 18:39 ../
-rw-------   1 05rw  staff          0 11 26 16:33 .localized
-rw-r--r--@  1 05rw  staff  106342400 12  5 18:21 dotnet-dev-osx-x64.1.0.0-preview2-003131.tar
-rw-r--r--@  1 05rw  staff  112025600 12  5 18:21 dotnet-dev-osx-x64.1.0.0-preview2-1-003177.tar
mac-05rw:Downloads 05rw$ mkdir dotnet101
mac-05rw:Downloads 05rw$ mkdir dotnet
mac-05rw:Downloads 05rw$ tar xvf dotnet-dev-osx-x64.1.0.0-preview2-003131.tar -C ./dotnet101/
x ./
x ./dotnet
x ./host/
 --- 中略 ---
x ./host/fxr/
x ./host/fxr/1.0.1/
x ./host/fxr/1.0.1/libhostfxr.dylib
mac-05rw:Downloads 05rw$ tar xvf dotnet-dev-osx-x64.1.0.0-preview2-1-003177.tar -C ./dotnet/
x ./
x ./dotnet
x ./host/
 --- 中略 ---
x ./host/fxr/
x ./host/fxr/1.1.0/
x ./host/fxr/1.1.0/libhostfxr.dylib


まず新しい方、ver1.1.0を、/usr/local/opt/dotnet/に配置します。

mac-05rw:Downloads 05rw$ sudo mv ./dotnet /usr/local/opt/dotnet



ver1.0.1の方は、テキストファイルとdotnetコマンドを削除して...

mac-05rw:Downloads 05rw$ ls -alF ./dotnet101/
total 352
drwxr-xr-x  8 05rw  staff     272 12  5 19:25 ./
drwx------+ 6 05rw  staff     204 12  5 19:16 ../
-rw-r--r--  1 05rw  staff    9410  6 16 09:15 LICENSE.txt             <- これと、
-rw-r--r--  1 05rw  staff    8103  6 16 09:15 ThirdPartyNotices.txt   <- これと、
-rwxr-xr-x  1 05rw  staff  155976  6 16 09:19 dotnet*                 <- これを削除
drwxr-xr-x  3 05rw  staff     102  9  1 07:59 host/
drwxr-xr-x  3 05rw  staff     102  9  1 07:59 sdk/
drwxr-xr-x  3 05rw  staff     102  9  1 07:59 shared/
mac-05rw:Downloads 05rw$ rm ./dotnet101/*.txt
mac-05rw:Downloads 05rw$ rm ./dotnet101/dotnet 

残った3つのフォルダを、/usr/local/opt/dotnet/に上書きコピーします。

mac-05rw:Downloads 05rw$ cp -Rf ./dotnet101/* /usr/local/opt/dotnet/



二つのバージョンが、併存してますね!

mac-05rw:Downloads 05rw$ ls -alF /usr/local/opt/dotnet/host/fxr/
total 0
drwxr-xr-x  4 05rw  staff  136 12  5 19:20 ./
drwxr-xr-x  3 05rw  staff  102 12  5 19:12 ../
drwxr-xr-x  3 05rw  staff  102 12  5 19:20 1.0.1/
drwxr-xr-x  3 05rw  staff  102 12  5 19:12 1.1.0/

/usr/local/bin/の下へ、シンボリックリンクを作ります。

mac-05rw:Downloads 05rw$ sudo ln -s /usr/local/opt/dotnet/dotnet /usr/local/bin/

以上でインストール終了です。

mac-05rw:Downloads 05rw$ dotnet --version
1.0.0-preview2-1-003177

動いてます!


ASP.NET Coreプロジェクトを実行してみる

ソースをgitから貰ってきて、動かしてみましょう。
CentOS7-GitBucketサーバ のIPアドレスhostsに追記してから、git cloneします。

mac-05rw:Downloads 05rw$ git clone http://git.centos7.local/git/05rw/dotnet_sample.git
Cloning into 'dotnet_sample'...
Username for 'http://git.centos7.local': 05rw
Password for 'http://05rw@git.centos7.local': 
remote: Counting objects: 102, done
remote: Finding sources: 100% (102/102)
remote: Getting sizes: 100% (95/95)
remote: Total 102 (delta 4), reused 102 (delta 4)
Receiving objects: 100% (102/102), 517.99 KiB | 0 bytes/s, done.
Resolving deltas: 100% (4/4), done.
Checking connectivity... done.

ソースがもらえました。
プロジェクトのルートに移動して、restorebuildを試します...。

mac-05rw:Downloads 05rw$ cd dotnet_sample/src/WebApplication1
mac-05rw:WebApplication1 05rw$ dotnet restore

Welcome to .NET Core!
---------------------
Learn more about .NET Core @ https://aka.ms/dotnet-docs. Use dotnet --help to see available commands or go to https://aka.ms/dotnet-cli-docs.
 --- 中略 ---
log  : Writing lock file to disk. Path: /Users/vm/Downloads/dotnet_sample/src/WebApplication1/project.lock.json
log  : ./dotnet_sample/src/WebApplication1/project.json
log  : Restore completed in 44161ms.
mac-05rw:WebApplication1 05rw$  dotnet build
Project WebApplication1 (.NETCoreApp,Version=v1.0) will be compiled because expected outputs are missing
Compiling WebApplication1 for .NETCoreApp,Version=v1.0

Compilation succeeded.
    0 Warning(s)
    0 Error(s)

Time elapsed 00:00:03.0704619
 

おおー、ビルドも通りましたね。
実行してみますか。

mac-05rw:WebApplication1 05rw$ dotnet run
Hosting environment: Production
Content root path: /Users/vm/Downloads
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

待機状態になりました!

ブラウザからアクセスしてみます。
せっかくGUIがあるので、ローカルのSafariから...
f:id:try_dot_net_core:20161205211421j:plain
動いてます!



今回分のソースコードはこちら。
前回から特に変更ありません。
github.com

Linux(CentOS7)で、ASP.NET Coreアプリのビルド自動化(2)

前回の続きです。必要なツール類を、概ねインストールできました。
今回は、ツールの初期設定から連携動作確認まで持っていきます。

Gitを入れてなかった

GitBucketでGitを受け付けるサーバは入ったのですが、コマンドラインツールのgitを入れるのを忘れてました。
Jenkinsが使うので、入れときます。

[root@centos7 ~]# yum -y install git
読み込んだプラグイン:fastestmirror
Loading mirror speeds from cached hostfile
  --- 中略 ---
  rsync.x86_64 0:3.0.9-17.el7

完了しました!

CentOS7側の hosts を編集

今のところCentOS7は検証環境なので、DNSによる名前解決ができません。
前回の開発用Windows機と同様に、/etc/hostsドメイン名を書き込んでおきます。

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

# --- 下記行を追記 ---
127.0.0.1   dotnet.centos7.local git.centos7.local jenkins.centos7.local

名前解決、出来てますかね?

[root@centos7 ~]# ping dotnet.centos7.local
PING dotnet.centos7.local (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.019 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.055 ms
^C
--- dotnet.centos7.local ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.019/0.037/0.055/0.018 ms
[root@centos7 ~]# ping git.centos7.local
PING dotnet.centos7.local (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.019 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.055 ms
^C
--- dotnet.centos7.local ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.019/0.037/0.055/0.018 ms
[root@centos7 ~]# ping jenkins.centos7.local
PING dotnet.centos7.local (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.021 ms
^C
--- dotnet.centos7.local ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.021/0.021/0.021/0.000 ms
[root@centos7 ~]# ping localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.021 ms
^C
--- localhost ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.021/0.021/0.021/0.000 ms

大丈夫ですね。

GitBucketのセットアップ

GitBucketに、ASP.NET Coreアプリ用のリポジトリを作っておきます。

git.centos7.localにアクセスして、ログインします。 f:id:try_dot_net_core:20161204111801j:plain

まずは初期ユーザー root でログイン。
初期状態のパスワードは root です。 f:id:try_dot_net_core:20161204103058j:plain

このあと、

  • rootユーザーのパスワードを変更
  • 一般ユーザー「05rw」を追加
  • ユーザー「05rw」のリポジトリdotnet_sample」を追加

などなどをやりました。 f:id:try_dot_net_core:20161204111544j:plain

開発用Windows機上の ASP.NET Coreプロジェクトファイル一式を、Gitリポジトリに追加します。
f:id:try_dot_net_core:20161204112925j:plain

GitBucket上でも、追加されたファイルが確認できますね。
f:id:try_dot_net_core:20161204113242j:plain

Jenkinsのセットアップ

次はJenkins。
インストール手順は、ほぼこちらにあるとおりをなぞります。

jenkins.centos7.localにアクセスします。
初回アクセス時には、アンロック用文字列を入力が必要です。
f:id:try_dot_net_core:20161204113951j:plain

画面の赤字のパスにあるファイルを開いて、文字列をコピペします。

[root@centos7 ~]# cat /home/webroot/jenkins/data/secrets/initialAdminPassword
--- アンロック用文字列が、記号なし小文字のみの英数で表示されます ---

次はプラグインのインストール内容を選びます。
お勧め一式を入れてくれるそうなので、左側の青いボタンを選びます。
f:id:try_dot_net_core:20161204114717j:plain

プラグインのインストール進捗が全て終わると、管理者ユーザー設定になります。
f:id:try_dot_net_core:20161204115132j:plain

初期設定が完了すると、ダッシュボードが表示されます。
GitBucket連携用プラグインをインストールするため、「Jenkinsの管理」へ。 f:id:try_dot_net_core:20161204115820j:plain

リバースプロキシの警告が出ちゃってるんですが、どうにも直りませんでした。
ぐぐっても、JenkinsURLのポート指定解除くらいしか出てこない...?
放っといて、「プラグインの管理」に行きます。
f:id:try_dot_net_core:20161204120612j:plain

利用可能タブを開いて、フィルターに"Gitb"と入力すると。
出てきましたね、「GitBucket Plugin」
チェックを入れて「再起動せずにインストール」を選びます。
f:id:try_dot_net_core:20161204120906j:plain

成功したようですね。
f:id:try_dot_net_core:20161204121208j:plain

参考:
JenkinsとGitBucketを連携し、pushされたら自動的にソースを取得する(GitBucket Plugin)

Jenkinsにジョブを追加する

やることが無くてひまぷーなJenkinsさんに、早速お仕事を教えてあげましょう。
ふふっ、世の中は厳しいんだぜ。

改めてダッシュボードに戻り、「新規ジョブ作成」を選びます。
f:id:try_dot_net_core:20161204121452j:plain

ジョブ名称を入力して、「フリースタイル・プロジェクトのビルド」を選びます。
f:id:try_dot_net_core:20161204124858j:plain

ジョブの詳細設定を入力する画面になりました。
「GitBucket」セクションで、上で作ったリポジトリのトップURL http://git.centos7.local/05rw/dotnet_sampleを入力します。
f:id:try_dot_net_core:20161204122333j:plain

ソースコード管理」セクションで、同リポジトリのクローン用URL http://git.centos7.local/git/05rw/dotnet_sample.git を入力します。
エラー表示が出ます。「Authentication failed」とのこと。
認証情報も追加しましょう。
Credentials項目の「追加」メニューを押し、Jenkins を選びます。
f:id:try_dot_net_core:20161204123141j:plain

設定項目が沢山並んでますが、ユーザー名とパスワードだけ入力します。
f:id:try_dot_net_core:20161204123524j:plain

あれー?エラー消えてない?
追加した Credentials は、自動で選択してくれないようですね。
f:id:try_dot_net_core:20161204123725j:plain

「ビルド・トリガ」セクションで、「Build when a change is pushed ot GitBucket」にチェックを入れます。
f:id:try_dot_net_core:20161204123932j:plain

「ビルド」セクションで、「ビルド手順の追加」メニューから「シェルの実行」を選びます。
f:id:try_dot_net_core:20161204124143j:plain

シェルスクリプトを入力します。
f:id:try_dot_net_core:20161204152630j:plain dotnetコマンドrestore, build, publishのリファレンスを参考に、スクリプトを書きます。
build, publishには記述がありませんが、restoreと同様に第一引数にプロジェクトパスをセットできるようです。

Jenkinsはジョブを実行すると、[Jenkinsデータフォルダ]/[ジョブ名]/の下に、Gitリポジトリのファイル一式を展開します。
スクリプトで指定するパスは、そのあたりを念頭に置いて書きます。

dotnet restore /home/webroot/jenkins/data/workspace/dotnet_sample_build/src/WebApplication1/
dotnet build /home/webroot/jenkins/data/workspace/dotnet_sample_build/src/WebApplication1/
systemctl stop dotnet_sample
dotnet publish /home/webroot/jenkins/data/workspace/dotnet_sample_build/src/WebApplication1/ --configuration Release --output /home/webroot/dotnet_sample/bin
systemctl start dotnet_sample

やれやれ、やっとジョブ情報を入力しおわりました。
保存して戻ります。
f:id:try_dot_net_core:20161204131534j:plain

ジョブが出来ましたね!
f:id:try_dot_net_core:20161204131803j:plain

「ビルド実行」を試してみます。
左下のビルド履歴に進捗が表示され、しばらく待つと履歴行が増えていますね。 f:id:try_dot_net_core:20161204134710j:plain

記念すべき初回ビルド#1の詳細内容は、ビルド履歴行の左端のをクリックすると出てきます。
f:id:try_dot_net_core:20161204135442j:plain

ユーザー05rwが実行
ビルドします。 ワークスペース: /home/webroot/jenkins/data/workspace/dotnet_sample_build
 > git rev-parse --is-inside-work-tree # timeout=10
Fetching changes from the remote Git repository
 > git config remote.origin.url http://git.centos7.local/git/05rw/dotnet_sample.git # timeout=10
Fetching upstream changes from http://git.centos7.local/git/05rw/dotnet_sample.git
 > git --version # timeout=10
using GIT_ASKPASS to set credentials 
 > git fetch --tags --progress http://git.centos7.local/git/05rw/dotnet_sample.git +refs/heads/*:refs/remotes/origin/*
 > git rev-parse refs/remotes/origin/master^{commit} # timeout=10
 > git rev-parse refs/remotes/origin/origin/master^{commit} # timeout=10
Checking out Revision c303273cfc10f328edfb4ab4d97cc965b949592c (refs/remotes/origin/master)
 > git config core.sparsecheckout # timeout=10
 > git checkout -f c303273cfc10f328edfb4ab4d97cc965b949592c
 > git rev-list c303273cfc10f328edfb4ab4d97cc965b949592c # timeout=10
[dotnet_sample_build] $ /bin/sh -xe /tmp/hudson9163061906313740256.sh
+ dotnet restore /home/webroot/jenkins/data/workspace/dotnet_sample_build/src/WebApplication1/
log  : Restoring packages for /home/webroot/jenkins/data/workspace/dotnet_sample_build/src/WebApplication1/project.json...
log  : Restoring packages for tool 'BundlerMinifier.Core' in /home/webroot/jenkins/data/workspace/dotnet_sample_build/src/WebApplication1/project.json...
log  : Restoring packages for tool 'Microsoft.AspNetCore.Razor.Tools' in /home/webroot/jenkins/data/workspace/dotnet_sample_build/src/WebApplication1/project.json...
log  : Restoring packages for tool 'Microsoft.AspNetCore.Server.IISIntegration.Tools' in /home/webroot/jenkins/data/workspace/dotnet_sample_build/src/WebApplication1/project.json...
log  : Writing lock file to disk. Path: /home/webroot/jenkins/data/workspace/dotnet_sample_build/src/WebApplication1/project.lock.json
log  : /home/webroot/jenkins/data/workspace/dotnet_sample_build/src/WebApplication1/project.json
log  : Restore completed in 9050ms.
+ dotnet build /home/webroot/jenkins/data/workspace/dotnet_sample_build/src/WebApplication1/
Project WebApplication1 (.NETCoreApp,Version=v1.0) will be compiled because expected outputs are missing
Compiling WebApplication1 for .NETCoreApp,Version=v1.0

Compilation succeeded.
    0 Warning(s)
    0 Error(s)

Time elapsed 00:00:02.1568893
 

+ systemctl stop dotnet_sample
+ dotnet publish /home/webroot/jenkins/data/workspace/dotnet_sample_build/src/WebApplication1/ --configuration Release --output /home/webroot/dotnet_sample/bin
Publishing WebApplication1 for .NETCoreApp,Version=v1.0
bower ESUDO         Cannot be run with sudo
Additional error details:
Since bower is a user command, there is no need to execute it with superuser permissions.
If you're having permission errors when using bower without sudo, please spend a few minutes learning more about how your system should work and make any necessary repairs.
http://www.joyent.com/blog/installing-node-and-npm
https://gist.github.com/isaacs/579814
You can however run a command with sudo using --allow-root option
Bundling with configuration from /home/webroot/jenkins/data/workspace/dotnet_sample_build/src/WebApplication1/bundleconfig.json
Processing wwwroot/css/site.min.css
  Bundled
  Minified
Processing wwwroot/js/site.min.js
  Bundled
Project WebApplication1 (.NETCoreApp,Version=v1.0) will be compiled because expected outputs are missing
Compiling WebApplication1 for .NETCoreApp,Version=v1.0

Compilation succeeded.
    0 Warning(s)
    0 Error(s)

Time elapsed 00:00:02.0746785
 

Configuring the following project for use with IIS: '/home/webroot/dotnet_sample/bin'
Updating web.config at '/home/webroot/dotnet_sample/bin/web.config'
Configuring project completed successfully
publish: Published to /home/webroot/dotnet_sample/bin
Published 1/1 projects successfully
+ systemctl start dotnet_sample
Finished: SUCCESS

参考:
dotnet-restore
dotnet-build
dotnet-publish

GitBucketがJenkinsをキックするように

Jenkinsの手動ビルドはできたんですが、まだです。
WebHookを利用して、GitBucketからJenkinsに通知を送るようにしないと、やはりJenkinsさんはひまぷーなままです。

Jenkinsが受け取るWebHookURLは、ジョブ設定ビルド・トリガのヘルプメッセージに書いてあります。
http://your.jenkins.host/jenkins/gitbucket-webhook/とな。
URLの中の/jenkins/はデフォルトのプレフィクスなので、ウチでは使いません。
設定するURLは、http://jenkins.centos7.local/gitbucket-webhook/ となりますね。
f:id:try_dot_net_core:20161204144823j:plain

GitBucketに戻ります。
左ペインのdotnet_sampleリポジトリを開きます。
f:id:try_dot_net_core:20161204145611j:plain

リポジトリ詳細画面の左ペインから、Settinsgを開きます。
f:id:try_dot_net_core:20161204145749j:plain

右ペインがリポジトリ設定に切り替わるので、Service Hooksタブを開いて「Add Webhook」を押します。
f:id:try_dot_net_core:20161204150054j:plain

WebHook編集画面が出てきます。
PayloadURLへ、先ほどのJenkins側WebHookURLを入力します。
その他はデフォルトですね。
f:id:try_dot_net_core:20161204150341j:plain

「Add Webhook」ボタンを押すと、WebHookが作られました。
f:id:try_dot_net_core:20161204150609j:plain

自動化されたか、試してみる

さて、Jenkinsさんがキチンと労働しているか、確かめてみましょう!

現状のdotnet.centos7.localの表示は、こんな感じ。
Visual Studioが作ったテンプレートそのままです。
f:id:try_dot_net_core:20161204141415j:plain

開発用Windows機の方で、このプロジェクトを開いて編集してみましょう。
f:id:try_dot_net_core:20161204141629j:plain

Visual Studio 2015 Update3 で、プロジェクトのViews/Shared/_Layout.cshtmlを開きます。
f:id:try_dot_net_core:20161204142518j:plain

<body>直下に、<div>を差し込んでみました。
f:id:try_dot_net_core:20161204150910j:plain

保存してコミット&プッシュします。
f:id:try_dot_net_core:20161204151128j:plain

おや、Jenkinsさんに反応が。
f:id:try_dot_net_core:20161204151310j:plain

ブラウザから、ASP.NET Coreアプリを見てみます。
f:id:try_dot_net_core:20161204152950j:plain

なんかテキストが、割り込んでますね!!!

長かったですが、これでやっと!
WindowsVisual Studioを操作するだけで、Linux上のASP.NET Coreアプリが更新されるようになりました。
お手軽に、なったぞー!!



今回分のソースコードはこちら。
Jenkinsによる自動ビルド確認のため、ViewのHTMLを書き換えています。
github.com

Linux(CentOS7)で、ASP.NET Coreアプリのビルド自動化(1)

ASP.NET Coreアプリを、サービス化することが出来ました。
しかし、まだPHPのお手軽さ加減には、一歩届きません。

PHPでは、ソースを書き換えただけで、すぐに動作が変わってくれます。
が、ASP.NET Coreはビルドしなきゃいけません。
その都度、sshで入って操作するの、面倒です嫌です。

そこで、Gitを経由したビルドの自動化を試みます。
導入するのは、GitBucketとJenkinsです。

javaの導入

ひとまずは、現在インストール済みの全パッケージを、最新に更新します。

[root@centos7 ~]# yum update

続いて、Javaです。
GitBucket, Jenkinsの両方ともJavaアプリなので、先に入れておきます。

このへんを参考に、一番新しいOpenJDK1.8系パッケージを見てみます。

[root@centos7 ~]# yum list | grep java-1.8
java-1.8.0-openjdk.x86_64               1:1.8.0.111-1.b15.el7_2        updates
java-1.8.0-openjdk-accessibility.x86_64 1:1.8.0.111-1.b15.el7_2        updates
java-1.8.0-openjdk-accessibility-debug.x86_64
java-1.8.0-openjdk-debug.x86_64         1:1.8.0.111-1.b15.el7_2        updates
java-1.8.0-openjdk-demo.x86_64          1:1.8.0.111-1.b15.el7_2        updates
java-1.8.0-openjdk-demo-debug.x86_64    1:1.8.0.111-1.b15.el7_2        updates
java-1.8.0-openjdk-devel.x86_64         1:1.8.0.111-1.b15.el7_2        updates
java-1.8.0-openjdk-devel-debug.x86_64   1:1.8.0.111-1.b15.el7_2        updates
java-1.8.0-openjdk-headless.x86_64      1:1.8.0.111-1.b15.el7_2        updates
java-1.8.0-openjdk-headless-debug.x86_64
java-1.8.0-openjdk-javadoc.noarch       1:1.8.0.111-1.b15.el7_2        updates
java-1.8.0-openjdk-javadoc-debug.noarch 1:1.8.0.111-1.b15.el7_2        updates
java-1.8.0-openjdk-src.x86_64           1:1.8.0.111-1.b15.el7_2        updates
java-1.8.0-openjdk-src-debug.x86_64     1:1.8.0.111-1.b15.el7_2        updates
[root@centos7 ~]#

ほうほう、ありますね。
こちらによると、1.8.0-openjdk,1.8.0-openjdk-headlessを入れておけばよさげ。
また、あとから使う予定のwgetも一緒にインストールします。

[root@centos7 ~]# yum -y install java-1.8.0-openjdk java-1.8.0-openjdk-headless wget
読み込んだプラグイン:fastestmirror
epel/x86_64/metalink                                     | 5.0 kB     00:00
epel                                                     | 4.3 kB     00:00
  --- 中略 ---
  xorg-x11-font-utils.x86_64 1:7.5-20.el7
  xorg-x11-fonts-Type1.noarch 0:7.5-9.el7

完了しました!

どれどれ?

[root@centos7 ~]# java -version
openjdk version "1.8.0_111"
OpenJDK Runtime Environment (build 1.8.0_111-b15)
OpenJDK 64-Bit Server VM (build 25.111-b15, mixed mode)

java、動いてますね。

参考:
参考メモ/CentOS7 の OpenJDK パッケージの構成メモ

GitBucketの導入

バイナリとデータの配置先フォルダを作ります。

[root@centos7 ~]# mkdir -p /home/webroot/gitbucket/bin
[root@centos7 ~]# mkdir -p /home/webroot/gitbucket/data

GitBucketのリリースページから、最新版のgitbucket.warを頂いてきます。

[root@centos7 ~]# cd /home/webroot/gitbucket/bin/
[root@centos7 bin]# wget https://github.com/gitbucket/gitbucket/releases/download/4.7.1/gitbucket.war
--2016-12-03 21:14:28--  https://github.com/gitbucket/gitbucket/releases/download/4.7.1/gitbucket.war
github.com (github.com) をDNSに問いあわせています... 192.30.253.112, 192.30.253.113
  --- 中略 ---
終了しました --2016-12-03 21:15:35--
経過時間: 1m 7s
ダウンロード完了: 1 ファイル、45M バイトを 1m 5s で取得 (707 KB/s)

apacheユーザーが実行出来るよう、所有権を変更しておきます。

[root@centos7 ~]# chown -Rf apache:apache /home/webroot/gitbucket

起動時のデータパスやプレフィクスなどを指定したかったので、tomcat経由でなく直接javaから起動させます。
先だってsystemdのサービス定義方法を覚えたところなので、早速追加しましょう。

[root@centos7 ~]# vi /etc/systemd/system/gitbucket.service

中身はこんなふうに。

[Unit]
    Description=GitBucket Service

    [Service]
    ExecStart=/usr/bin/java -jar /home/webroot/gitbucket/bin/gitbucket.war --gitbucket.home=/home/webroot/gitbucket/data --port=8002 --prefix=/
    WorkingDirectory=/home/webroot/gitbucket/data
    Restart=always
    RestartSec=10
    SyslogIdentifier=gitbucket
    User=apache

    [Install]
    WantedBy=multi-user.target

サービスを起動してみます。

[root@centos7 bin]# systemctl daemon-reload
[root@centos7 bin]# systemctl enable gitbucket
Created symlink from /etc/systemd/system/multi-user.target.wants/gitbucket.service to /etc/systemd/system/gitbucket.service.
[root@centos7 bin]# systemctl start gitbucket
[root@centos7 bin]# systemctl status gitbucket
● gitbucket.service - GitBucket Service
   Loaded: loaded (/etc/systemd/system/gitbucket.service; disabled; vendor preset: disabled)
   Active: active (running) since 日 2016-12-04 00:17:42 JST; 10s ago
 Main PID: 27599 (java)
   CGroup: /system.slice/gitbucket.service
           mq27599 /usr/bin/java -jar /home/webroot/gitbucket/bin/gitbucket.w...

12月 04 00:17:45 centos7.local gitbucket[27599]: Using job-store 'org.quartz...
12月 04 00:17:45 centos7.local gitbucket[27599]: 00:17:45.400 [main] INFO  o...
12月 04 00:17:45 centos7.local gitbucket[27599]: 00:17:45.400 [main] INFO  o...
12月 04 00:17:45 centos7.local gitbucket[27599]: 00:17:45.401 [main] INFO  o...
12月 04 00:17:45 centos7.local gitbucket[27599]: [INFO] [12/04/2016 00:17:45...
12月 04 00:17:45 centos7.local gitbucket[27599]: 00:17:45.420 [main] INFO  o...
12月 04 00:17:45 centos7.local gitbucket[27599]: 00:17:45.423 [main] INFO  o...
12月 04 00:17:45 centos7.local gitbucket[27599]: 2016-12-04 00:17:45.962:INF...
12月 04 00:17:45 centos7.local gitbucket[27599]: 2016-12-04 00:17:45.971:INF...
12月 04 00:17:45 centos7.local gitbucket[27599]: 2016-12-04 00:17:45.971:INF...
Hint: Some lines were ellipsized, use -l to show in full.

サービス定義にある、サーバの8002番ポートにブラウザからアクセスしてみます。
f:id:try_dot_net_core:20161204002140j:plain
GitBucket、起動してます!

参考:
GitHub gitbucket/gitbucket/release

Jenkinsの導入

概ねGitBucketと同じような流れです。
バイナリとデータの配置先フォルダを作ります。

[root@centos7 ~]# mkdir -p /home/webroot/jenkins/bin
[root@centos7 ~]# mkdir -p /home/webroot/jenkins/data

Jenkinsバイナリ配布ページから、最新版のjenkins.warを貰ってきます。

[root@centos7 ~]# cd /home/webroot/jenkins/bin/
[root@centos7 bin]# wget http://mirrors.jenkins-ci.org/war/latest/jenkins.war
--2016-12-04 00:35:16--  http://mirrors.jenkins-ci.org/war/latest/jenkins.war
mirrors.jenkins-ci.org (mirrors.jenkins-ci.org) をDNSに問いあわせています... 52.202.51.185
  --- 中略 ---
100%[======================================>] 68,851,608   986KB/s 時間 1m 47s

2016-12-04 00:37:04 (630 KB/s) - `jenkins.war' へ保存完了 [68851608/68851608]

apacheユーザーが実行出来るよう、所有権を変更しておきます。

[root@centos7 bin]# chown -Rf apache:apache /home/webroot/jenkins

こちらも起動時のプレフィクスを指定したいので、javaから起動させます。
jenkinsサービスを追加します。

[root@centos7 ~]# vi /etc/systemd/system/jenkins.service

中身はこんなふうに。

[Unit]
    Description=Jenkins Service

    [Service]
    ExecStart=/usr/bin/java -jar /home/webroot/jenkins/bin/jenkins.war --httpPort=8003 --prefix=/
    WorkingDirectory=/home/webroot/jenkins/data
    Restart=always
    RestartSec=10
    SyslogIdentifier=jenkins
    User=root
    Environment=JENKINS_HOME=/home/webroot/jenkins/data

    [Install]
    WantedBy=multi-user.target

環境変数設定Environmentが増えているのがミソです。
GitBucketと違い、開始時にデータフォルダを指定するオプションがありません。
そのためこのあたりを参考に、環境変数でデータフォルダを指定しています。
こういうの、まとめておくとバックアップがラクチンですから。

また、実行権限はrootにしています。
お行儀の悪い設定ではあるんですが...。

Jenkinsはビルド等のシェルスクリプト実行時、サービス再起動などのroot権限が必要な処理を行います。
root以外のユーザーでJenkinsが実行されている場合、visudo設定でsudoの認証を回避することになります。
そうすると、セキュリティもクソもないんですよね。

まあ、Jenkinsの攻撃が成功してしまったらオワリだ、ということで、肚を括りましょう:-)

さて、Jenkinsも起動してみましょう。

[root@centos7 ~]# systemctl daemon-reload
[root@centos7 ~]# systemctl enable jenkins
Created symlink from /etc/systemd/system/multi-user.target.wants/jenkins.service to /etc/systemd/system/jenkins.service.
[root@centos7 ~]# systemctl start jenkins
[root@centos7 ~]# systemctl status jenkins
● jenkins.service - Jenkins Service
   Loaded: loaded (/etc/systemd/system/jenkins.service; enabled; vendor preset: disabled)
   Active: active (running) since 日 2016-12-04 01:43:20 JST; 6s ago
 Main PID: 28999 (java)
   CGroup: /system.slice/jenkins.service
           mq28999 /usr/bin/java -jar /home/webroot/jenkins/bin/jenkins.war -...

12月 04 01:43:24 centos7.local jenkins[28999]: ****************************...*
12月 04 01:43:24 centos7.local jenkins[28999]: ****************************...*
12月 04 01:43:24 centos7.local jenkins[28999]: ****************************...*
12月 04 01:43:24 centos7.local jenkins[28999]: Jenkins initial setup is req....
12月 04 01:43:24 centos7.local jenkins[28999]: Please use the following pas...:
12月 04 01:43:24 centos7.local jenkins[28999]: efad29c130da48e3980ebc59b032b8ab
12月 04 01:43:24 centos7.local jenkins[28999]: This may also be found at: /...d
12月 04 01:43:24 centos7.local jenkins[28999]: ****************************...*
12月 04 01:43:24 centos7.local jenkins[28999]: ****************************...*
12月 04 01:43:24 centos7.local jenkins[28999]: ****************************...*
Hint: Some lines were ellipsized, use -l to show in full.

起動したみたい?

f:id:try_dot_net_core:20161204014603j:plain
初期設定画面ですね!

参考:
Starting and Accessing Jenkins
Change JENKINS_HOME on Red Hat Linux?

apache-VirtualHost化

ASP.NET Coreアプリに加えて、GitBucketとJenkinsが稼働し始めました。
外部パートナーからのアクセスを考えて、全てapache経由で動くように調整します。

/etc/httpd/conf/httpd.confを編集して VirtualHostを3つ作ります。
dotnet.centos7.local, git.centos7.local, jenkins.centos7.local の3つのドメイン名を定義しました。

#---前回追加した箇所をコメントアウト---
#ProxyPreserveHost On
#ProxyPass / http://localhost:5000/
#ProxyPassReverse / http://localhost:5000/

#---ここから追記---
#-------------------------------------------------------
# Service dotnet.centos7.local
#-------------------------------------------------------
<VirtualHost *:80>
        ServerName dotnet.centos7.local
        ErrorLog /var/log/httpd/dotnet.centos7.local.error.log
        CustomLog /var/log/httpd/dotnet.centos7.local.access.log common

        ProxyPreserveHost On
        ProxyPass / http://localhost:5000/
        ProxyPassReverse / http://localhost:5000/
</VirtualHost>

#-------------------------------------------------------
# Service git.centos7.local
#-------------------------------------------------------
<VirtualHost *:80>
        ServerName git.centos7.local
        ErrorLog /var/log/httpd/git.centos7.local.error.log
        CustomLog /var/log/httpd/git.centos7.local.access.log common

        ProxyPreserveHost On
        ProxyPass / http://localhost:8002/
        ProxyPassReverse / http://localhost:8002/
</VirtualHost>

#-------------------------------------------------------
# Service jenkins.centos7.local
#-------------------------------------------------------
<VirtualHost *:80>
        ServerName jenkins.centos7.local
        ErrorLog /var/log/httpd/jenkins.centos7.local.error.log
        CustomLog /var/log/httpd/jenkins.centos7.local.access.log common

        ProxyPreserveHost On
        ProxyPass / http://localhost:8003/
        ProxyPassReverse / http://localhost:8003/
</VirtualHost>

開発用Windows機のhostsファイルにも、上記3ドメインを書き込みます。
f:id:try_dot_net_core:20161204020845j:plain

ブラウザから、確認してみましょう。 f:id:try_dot_net_core:20161204021215j:plain
ん、おっけーです!



今回分のソースコードはこちら。
まだ、Visual Studioが生成するテンプレートのままです。
github.com

次回、いよいよ連動ビルド設定に入ります!

Linux(CentOS7)で、ASP.NET Coreアプリをサービス化する

ASP.NET Coreプロジェクトで、dotnet publishコマンドの動作が確認できました。
今のところdotnet runもしくはdotnet [dllファイル名]で動作確認しています。

しかし実際にサービス運用するのに、このままシェルを占有させる訳にもいきません。
PHPと違って、apache がプログラムをキックしてくれるわけでもなく。
何かの不具合で異常終了しまうと、こわい。

というわけで、OSにプログラムの面倒を見てもらえるように、サービス化します。

systemd用のサービス定義を書く

公式ドキュメントをあたると、どうやらsystemdを使うようです。

sudo nano /etc/systemd/system/kestrel-hellomvc.service の、nanoってナニソレ?と思ったら、テキストエディタなんですね。
ふむふむ、じゃviでいいや。
サービス定義ファイルを作ります。

[root@centos7 ~]# vi /etc/systemd/system/dotnet_sample.service

中身はこんな感じに。

[Unit]
    Description=Service Sample on CentOS7

    [Service]
    ExecStart=/usr/bin/dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll
    Restart=always
    RestartSec=10
    SyslogIdentifier=dotnet_sample
    User=root
    Environment=ASPNETCORE_ENVIRONMENT=Production

    [Install]
    WantedBy=multi-user.target

公式サンプルをコピペして、実行ファイルのパス、実行ユーザーなどを書き換えました。

さて、どうなるでしょう?

[root@centos7 system]# systemctl daemon-reload
[root@centos7 system]# systemctl start dotnet_sample
[root@centos7 system]# systemctl status dotnet_sample
● dotnet_sample.service - Service Sample on CentOS7
   Loaded: loaded (/etc/systemd/system/dotnet_sample.service; enabled; vendor preset: disabled)
   Active: active (running) since 土 2016-12-03 17:56:09 JST; 6s ago
 Main PID: 3618 (dotnet)
   CGroup: /system.slice/dotnet_sample.service
           mq3618 /usr/bin/dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll

12月 03 17:56:09 centos7.local systemd[1]: Started Service Sample on CentOS7.
12月 03 17:56:09 centos7.local systemd[1]: Starting Service Sample on CentOS7...
12月 03 17:56:10 centos7.local dotnet_sample[3618]: Hosting environment: Production
12月 03 17:56:10 centos7.local dotnet_sample[3618]: Content root path: /
12月 03 17:56:10 centos7.local dotnet_sample[3618]: Now listening on: http://localhost:5000
12月 03 17:56:10 centos7.local dotnet_sample[3618]: Application started. Press Ctrl+C to shut down.

あー。
一見、動いてるように見えますが、Content root path: /と出てます。
publish先のパスでなく、ルートディレクトリになっちゃってます。
前回末尾に書いた、Internal Server Errorになっちゃうヤツですね。
f:id:try_dot_net_core:20161203180017j:plain
はい、動いていません。
実行時のカレントパスを指定しないといけませんね。

参考:
Publish to a Linux Production Environment

カレントパスは、どうやって書く?

かなり頑張ってぐぐりました。
おかげさまで、図らずもsystemdのことがざっくり飲み込めました。

どうやら、*.service ファイルでWorkingDirectoryという項目を指定できるようです。

追記してみます。

[Unit]
    Description=Service Sample on CentOS7

    [Service]
    ExecStart=/usr/bin/dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll
    WorkingDirectory=/home/webroot/dotnet_sample/bin/   # <-この行を追記
    Restart=always
    RestartSec=10
    SyslogIdentifier=dotnet_sample
    User=root
    Environment=ASPNETCORE_ENVIRONMENT=Production

    [Install]
    WantedBy=multi-user.target

どうなるでしょう?

[root@centos7 system]# systemctl stop dotnet_sample
Error: No space left on device
Warning: dotnet_sample.service changed on disk. Run 'systemctl daemon-reload' to reload units.
[root@centos7 system]# systemctl daemon-reload
[root@centos7 system]# systemctl start dotnet_sample
[root@centos7 system]# systemctl status dotnet_sample
● dotnet_sample.service - Service Sample on CentOS7
   Loaded: loaded (/etc/systemd/system/dotnet_sample.service; enabled; vendor preset: disabled)
   Active: active (running) since 土 2016-12-03 18:09:45 JST; 7s ago
 Main PID: 3698 (dotnet)
   CGroup: /system.slice/dotnet_sample.service
           mq3698 /usr/bin/dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll

12月 03 18:09:45 centos7.local systemd[1]: Started Service Sample on CentOS7.
12月 03 18:09:45 centos7.local systemd[1]: Starting Service Sample on CentOS7...
12月 03 18:09:45 centos7.local dotnet_sample[3698]: Hosting environment: Production
12月 03 18:09:45 centos7.local dotnet_sample[3698]: Content root path: /home/webroot/dotnet_sample/bin
12月 03 18:09:45 centos7.local dotnet_sample[3698]: Now listening on: http://localhost:5000
12月 03 18:09:45 centos7.local dotnet_sample[3698]: Application started. Press Ctrl+C to shut down.

おっ。パスがセットできてますね!
動作はいかが?
f:id:try_dot_net_core:20161203175303j:plain 動きましたね~~!

参考:
Executing chdir before starting systemd service

実行権限をapacheに変える

いつまでも、rootで動かしてちゃダメですよね。一応公開を前提にするわけで。
というわけで、apacheユーザーで動作するように、設定を見直します。

dotnet_sample.serviceファイルより、実行ユーザーを変更します。

[Unit]
    Description=Service Sample on CentOS7

    [Service]
    ExecStart=/usr/bin/dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll
    WorkingDirectory=/home/webroot/dotnet_sample/bin/
    Restart=always
    RestartSec=10
    SyslogIdentifier=dotnet_sample
#    User=root
    User=apache
    Environment=ASPNETCORE_ENVIRONMENT=Production

    [Install]
    WantedBy=multi-user.target

これでいいはず...?

[root@centos7 system]# systemctl stop dotnet_sample
Warning: dotnet_sample.service changed on disk. Run 'systemctl daemon-reload' to reload units.
[root@centos7 system]# systemctl daemon-reload
[root@centos7 system]# systemctl start dotnet_sample
[root@centos7 system]# systemctl status dotnet_sample
● dotnet_sample.service - Service Sample on CentOS7
   Loaded: loaded (/etc/systemd/system/dotnet_sample.service; enabled; vendor preset: disabled)
   Active: activating (auto-restart) (Result: exit-code) since 土 2016-12-03 18:19:50 JST; 3s ago
  Process: 3748 ExecStart=/usr/bin/dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll (code=exited, status=203/EXEC)
 Main PID: 3748 (code=exited, status=203/EXEC)

12月 03 18:19:50 centos7.local systemd[1]: Unit dotnet_sample.service entered failed state.
12月 03 18:19:50 centos7.local systemd[1]: dotnet_sample.service failed.

あらー。起動出来なかった...。

原因なんだっけなーと、諸々探してみますと。

[root@centos7 dotnet]# pwd
/opt/dotnet
[root@centos7 dotnet]# ls -alF
合計 148
drwxr-xr-x. 5 root root     99 12月  2 16:35 ./
drwxr-xr-x. 3 root root     19 12月  2 16:31 ../
-rwxr--r--. 1 root root   9410 11月  3 08:49 LICENSE.txt*
-rwxr--r--. 1 root root   8103 11月  3 08:49 ThirdPartyNotices.txt*
-rwxr--r--. 1 root root 128693 11月  9 06:52 dotnet*
drwxr-xr-x. 3 root root     16 12月  2 16:35 host/
drwxr-xr-x. 4 root root     64 12月  2 16:52 sdk/
drwxr-xr-x. 3 root root     34 12月  2 16:35 shared/

あらっ。
dotnetコマンド実体ファイルの権限が、root以外で実行出来なくなってますやん。
こらあかん。
全員が実行出来るよう、サブフォルダを含めて一括修正します。

[root@centos7 dotnet]# cd ../
[root@centos7 opt]# pwd
/opt
[root@centos7 opt]# chmod -Rf 755 ./dotnet

どやっ?

[root@centos7 system]# systemctl stop dotnet_service
Failed to stop dotnet_service.service: Unit dotnet_service.service not loaded.
[root@centos7 system]# systemctl start dotnet_sample
[root@centos7 system]# systemctl status dotnet_sample
● dotnet_sample.service - Service Sample on CentOS7
   Loaded: loaded (/etc/systemd/system/dotnet_sample.service; enabled; vendor preset: disabled)
   Active: active (running) since 土 2016-12-03 18:30:04 JST; 1min 1s ago
 Main PID: 3875 (dotnet)
   CGroup: /system.slice/dotnet_sample.service
           mq3875 /usr/bin/dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll

12月 03 18:30:04 centos7.local systemd[1]: Started Service Sample on CentOS7.
12月 03 18:30:04 centos7.local systemd[1]: Starting Service Sample on CentOS7...
12月 03 18:30:04 centos7.local dotnet_sample[3875]: Hosting environment: Production
12月 03 18:30:04 centos7.local dotnet_sample[3875]: Content root path: /home/webroot/dotnet_sample/bin
12月 03 18:30:04 centos7.local dotnet_sample[3875]: Now listening on: http://localhost:5000
12月 03 18:30:04 centos7.local dotnet_sample[3875]: Application started. Press Ctrl+C to shut down.
12月 03 18:31:02 centos7.local systemd[1]: Started Service Sample on CentOS7.

おっしゃ!
イケましたな。

dotnetプロセスを殺してみる

これで、dotnet_sampleサービスが死んでもsystemdが再起動してくれる、はずです。
試してみます...。

[root@centos7 ~]# ps -A | grep dotnet
  3875 ?        00:00:00 dotnet
[root@centos7 ~]# kill 3875
-->(dotnet_sample.serviceファイルの RestartSec設定どおり、10秒待ってから)-->
[root@centos7 ~]# ps -A | grep dotnet
  3914 ?        00:00:00 dotnet

大丈夫!理不尽に殺害されても、生き返ります!

ちなみに、supervisorだと?

systemdが標準化する以前は、プロセス監視にsupervisorを使ってた、ようです。
や、すいません。
LinuxだとPHPオンリーで、監視が必要なサービスは書いたこと無かったんです...。

CentOS7では、yum install supervisorでインストールできました。
設定ファイルは/etc/supervisord.d/[各種サービス].iniに書きます。

こちらを参考に、こんな感じで動きました。

[program:dotnet_sample]
directory=/home/webroot/dotnet_sample/bin/
command=dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll
user=apache  ; 起動ユーザ
autostart=true
autorestart=true  ; プロセスダウン時に自動再起動
stdout_logfile=/var/log/supervisor/dotnet_sample.out.log ; 標準出力ログ
stderr_logfile=/var/log/supervisor/dotnet_sample.err.log
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=5
stdout_capture_maxbytes=1MB
redirect_stderr=true  ; エラー出力を標準出力にリダイレクト
environment=Hosting__Environment=Production,HOME=/home/webroot/dotnet_sample/bin/
stopsignal=INT

参考:
ASP.NET Core アプリを Ubuntu サーバーで公開



今回分のソースコードはこちら。
まだ、Visual Studioが生成するテンプレートのままです。
github.com