42
(主にdocker向けの) ASP.NET Coreの お気に入りの機能たち @tanaka_733 2017 10 23 Fukuoka.NET Conf 2017

ASP.NET Core のお気に入りの機能たち (docker向け)

Embed Size (px)

Citation preview

Page 1: ASP.NET Core のお気に入りの機能たち (docker向け)

(主にdocker向けの)ASP.NET Coreの

お気に入りの機能たち@tanaka_733

2017年10月23日 Fukuoka.NET Conf 2017

Page 2: ASP.NET Core のお気に入りの機能たち (docker向け)

自己紹介Red Hat K.K. 勤務◦Software Maintenance Engineer◦担当はOpenShiftと(いつの間にか)Microsoftとの協業分野全般◦ .NET Core on RHEL, Red Hat solutions on Azure, SQL Server on RHEL

◦会社Blog: Red Hat Developers

Personal◦福岡県北九州市出身◦ Microsoft MVP for VSDT◦ Blog: 銀の光と碧い空◦ Build Insiderで.NET Core連載中

VSDT: Visual Studio & Development Technologies

Page 3: ASP.NET Core のお気に入りの機能たち (docker向け)

今日のセッションのゴールDockerをはじめとしたコンテナ環境でASP.NET Coreを便利に使いたい

そんな時に役立つ機能のご紹介

※kubernetes (OpenShift)の機能とあわせて紹介していますが、他のオーケストレーションツール/サービスでも同じような機能があるはずですkubectl: kubernetsコマンド, oc: OpenShiftクライアントコマンド

Page 4: ASP.NET Core のお気に入りの機能たち (docker向け)

Agenda

◦Visual StudioでのDocker support

◦外部ファイルを使った設定の注入

◦複数コンテナでのセッション管理

◦リモートデバッグ

◦EF Core: コードファースト DB migration

Page 5: ASP.NET Core のお気に入りの機能たち (docker向け)
Page 6: ASP.NET Core のお気に入りの機能たち (docker向け)

Docker Support◦ ASP.NET Core プロジェクトのテンプレート選択画面

Page 7: ASP.NET Core のお気に入りの機能たち (docker向け)

Docker Support◦ ASP.NET Core プロジェクトのテンプレート選択画面

テンプレートによっては利用できない

Windows/Linuxコンテナ選択可 ソリューションフォルダを作らないと

うまく動作しない(バージョンがあった)

Page 8: ASP.NET Core のお気に入りの機能たち (docker向け)

何が起きるのか?◦Dockerfileの追加

◦単純なASP.NET Coreアプリのコンテナだったのが15.5 Previewではちょっと手の込んだ方法に…

◦docker-composeプロジェクトの追加

◦ docker composerファイルの追加

◦ローカルのdockerへの配置とデバッグの支援

◦機能自体はVisual Studio SDK側で実装されている

◦ Linux/Windowsコンテナの選択はdocker-composeプロジェクトで設定してある

Page 9: ASP.NET Core のお気に入りの機能たち (docker向け)

新しいDockerfileFROM microsoft/aspnetcore:2.0 AS base

WORKDIR /app

EXPOSE 80

FROM microsoft/aspnetcore-build:2.0 AS build

WORKDIR /src

COPY *.sln ./

COPY WebApplication1/WebApplication1.csproj WebApplication1/

RUN dotnet restore

COPY . .

WORKDIR /src/WebApplication1

RUN dotnet build -c Release -o /app

FROM build AS publish

RUN dotnet publish -c Release -o /app

FROM base AS final

WORKDIR /app

COPY --from=publish /app .

ENTRYPOINT ["dotnet", "WebApplication1.dll"]

Page 10: ASP.NET Core のお気に入りの機能たち (docker向け)

Docker imageの生成フロー

microsoft/aspnetcore:2.0

base

port80

microsoft/aspnetcore-build:2.0

build

final

port80entrypoint

solutionをコピーbuild

publish

publish

バイナリをコピー

Page 11: ASP.NET Core のお気に入りの機能たち (docker向け)

何がうれしい?◦最終的なコンテナサイズが小さくなった

◦今までは.NET Core SDK (Runtime+ビルドに必要なもの)をベースにしていたので、最初からサイズがでかい

◦Runtimeのみのコンテナではビルドできない

◦ビルド用のコンテナを別にして、そちらはSDKこみで。最終的な成果物のコンテナはRuntimeのみにした

◦(おまけ)OpenShiftもTemplateとして提供していますセッション後のハイパー宣伝タイムで!

Page 12: ASP.NET Core のお気に入りの機能たち (docker向け)

Dockerデバッグの仕組み

Page 13: ASP.NET Core のお気に入りの機能たち (docker向け)

Docker for Windows

Hyper-V

Docker用仮想マシン

コンテナ実行用軽量LinuxVM

Docker Engine Docker クライアント

Linuxコンテナプロセス

Page 14: ASP.NET Core のお気に入りの機能たち (docker向け)

デバッグ用コンテナ起動

Hyper-V

コンテナ実行用軽量LinuxVM

ホストOS(Windows)とファイル共有

vsdbgバイナリなど(Cドライブ)

プロジェクトファイル(保存場所のドライブ)tail -f /dev/null

で起動しっぱなし

その他NuGetパッケージなどもファイル共有

Page 15: ASP.NET Core のお気に入りの機能たち (docker向け)

ビルド

Hyper-V

コンテナ実行用軽量LinuxVM Windows側でプロジェクトをビルド

tail -f /dev/nullで起動しっぱなし

app.dll

Page 16: ASP.NET Core のお気に入りの機能たち (docker向け)

デバッグ開始

Hyper-V

コンテナ実行用軽量LinuxVM

dotnet app.dll

tail -f /dev/nullで起動しっぱなし

app.dll

./vsdbg vsdbg

コンテナ内でdotnetプロセスを開始デバッガープロセス開始SSHこしにリモートデバッグ接続

Page 17: ASP.NET Core のお気に入りの機能たち (docker向け)

(Note) dockerの状態PS C:\Tools> docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

e1e8b52cf67e aspnetcoreexample1:dev "tail -f /dev/null" About a minute ago Up About a minute 0.0.0.0:32768->80/tcp dockercompose9290894832686996463_aspnetcoreexample1_1

PS C:\Tools> docker exec -i -t e1e8b52cf67e /bin/bash

//なぜかpsコマンドが使えないので、/proc/<PID>を直接見る

# cat /proc/1/cmdline

tail -f /dev/null

# cat /proc/5/cmdline

/remote_debugger/vsdbg --interpreter=vscode

# cat /proc/13/cmdline

/usr/bin/dotnet --additionalProbingPath /root/.nuget/packages --additionalProbingPath /root/.nuget/fallbackpackagesbin/Debug/netcoreapp2.0/AspNetCoreExample1.dll

# cat /proc/820/cmdline

/bin/bash

Page 18: ASP.NET Core のお気に入りの機能たち (docker向け)
Page 19: ASP.NET Core のお気に入りの機能たち (docker向け)

.NET Core Debugger概要

19

GDB/LLDB

MICore

MIDE/Engine.Impl

MIDE(*)/AD7.Impl

VSCode Debugger

AD7 Interface

*MIDE: MIDebugEngine: GitHub repository*vsdbg can be used only in VS products and might not be distributed.

MIText

VS Debugger

VS Debugger Engine vsdbg

(closed license*)

windbg

See more:Architecture of MIEngine

Page 20: ASP.NET Core のお気に入りの機能たち (docker向け)

.NET CoreのDebuggerの特徴◦低レイヤーはwindbg(vsdbg?)、GDB/LLDBとOS固有

◦WindowsではVisual Studioがすべて面倒みてくれる

◦Linux (Mac)ではMIEngineというツールが面倒をみる

◦ MS製OSSだけど、バイナリの利用はVS製品のみ許可

◦ツールは違えどインターフェースは共通

◦WindowsとLinux(Mac)の間で相互にリモートデバッグが可能

Page 21: ASP.NET Core のお気に入りの機能たち (docker向け)

リモートのDockerに接続したい◦技術的には可能

◦ vsdbgのバイナリを手動インストール (VSから使う用途はOKのはず)

◦ sshコマンドの代わりにkubectl exec/oc rshなどを使えばよい

◦が、現状、機能としては存在しない

◦クローズド部分なのでVSIX(VS拡張)も作れない模様

◦Azureはkubernetes推しなので、将来対応するのでは?

◦ composerを直接はサポートしていないのでそこも対応を期待

Page 22: ASP.NET Core のお気に入りの機能たち (docker向け)

Visual Studio Code なら可能◦ launch.jsonに追加◦ SSHの代わりに任意のコマンドを指定できる

◦月曜の夜に会社ブログに書いた記事が公開されます{

"name": ".NET Core OpenShift Pod Remote Attach","type": "coreclr","request": "attach", "processId": "","pipeTransport": {

"pipeProgram": "oc", "pipeArgs": [ "exec", "-it", "<pod_name>", "--"], "quoteArgs":false, "debuggerPath": "/opt/app-root/vsdbg/vsdbg", "pipeCwd": "${workspaceRoot}"

},"justMyCode":false,"sourceFileMap": { "/opt/app-root/src": "${workspaceRoot}"}

}

Page 23: ASP.NET Core のお気に入りの機能たち (docker向け)
Page 24: ASP.NET Core のお気に入りの機能たち (docker向け)

設定ファイルの取り扱い◦ソースコード=バイナリを変更せずに、設定ファイルの差し替えで動作を変更したい

◦Docker環境でどうやって外部ファイルを注入する?◦1回アプリのコンテナイメージ作ったら、設定ファイルの変更だけのためにイメージ作り直したくないですよね?

Page 25: ASP.NET Core のお気に入りの機能たち (docker向け)

Add***File メソッドで設定の注入

Page 26: ASP.NET Core のお気に入りの機能たち (docker向け)

Dockerでの取り扱い◦設定ファイルを含んだvolumeをDocker起動時にマウントさせる

◦ Docker使わない環境でも指定したパスにファイルを置けばよい

◦ kubernetesの場合はConfigMapを使えます

$ kubectl create configmap myconfig --from-file=appsettings.json//pod.yamlspec:containers:- name: test-containervolumeMounts:- name: config-volume

mountPath: /opt/app-root/confvolumes:- name: config-volumeconfigMap:

name: myconfig

Page 27: ASP.NET Core のお気に入りの機能たち (docker向け)

機密情報を扱いたい場合◦DBのパスワードなど◦ソースコードリポジトリには入れたくない

◦アプリのコンテナイメージにも入れておきたくない

◦ASP.NET CoreのUserSecret機能は開発用途なので使うべきではない◦マシン固有の暗号キーでファイルに保存しておく機能

◦Azureの場合 Azure Key Vault と Managed Service Identity◦ 今のところPreviewでApp ServiceとAzure Functionsのみ利用可

◦ kubernetes/OpenShiftの場合 Secret機能

Page 28: ASP.NET Core のお気に入りの機能たち (docker向け)

Secret機能Base64エンコードした値を格納して、dockerコンテナにファイルもしくは環境変数としてマウント◦暗号化ではない。アクセスを制限できるという意味合いはある

Page 29: ASP.NET Core のお気に入りの機能たち (docker向け)
Page 30: ASP.NET Core のお気に入りの機能たち (docker向け)

複数コンテナでHTTPセッションデフォルトでは:◦コンテナごとにHTTPセッションをメモリ内に格納◦コンテナでない場合もプロセスごとに別々

つまり?◦コンテナへのロードバランシングがStickyセッションならコンテナが生きている限り問題なし

◦コンテナが死んだらセッションが維持できない◦ Stickyじゃないとそもそもセッションが維持できない

Page 31: ASP.NET Core のお気に入りの機能たち (docker向け)

container A

cnotainer B

container C

ASP.NET Core

ASP.NET Core

ASP.NET Core

それぞれのコンテナに別々にセッションデータが格納される

container AでHTTPセッション確立しても次のHTTPリクエストがcontainer Bだと確立したセッションの情報はない

Page 32: ASP.NET Core のお気に入りの機能たち (docker向け)

IDistributedCache & IDataProtectionIDistributedCache◦ 名前からしてこれだけ設定すれば十分な気がするこれがまちがい◦ 分散キャッシュを提供◦ セッションの格納先に指定できる◦ SQLServerとRedisを保存先とするライブラリASP.NET Coreチームが提供

IDataProtection◦ 暗号化のキー管理を提供◦ HTTPセッションの暗号化にも利用されている◦ デフォルトではコンテナ(マシン)ごとにキーを発行し、ローカルファイルに保存

◦ Network FilesystemとRedisとAzure Storage, Azure Fileを提供

Page 33: ASP.NET Core のお気に入りの機能たち (docker向け)

container A

container B

container C

ASP.NET Core

ASP.NET Core

ASP.NET Core

Session Data A’

containerごとに異なるキーセッションデータ自体を共有できても、キーが違うので復号できず意味がない

~/.aspnet

IDistributedCacheをRedisに設定するだけだと…

Page 34: ASP.NET Core のお気に入りの機能たち (docker向け)

machine A

machine B

machine C

ASP.NET Core

ASP.NET Core

ASP.NET Core

Session Data

IDataProtectionもRedisに設定

キー自体をRedisに保存して共有するのでOK!Redisが死んだ場合の考慮は必要

Page 35: ASP.NET Core のお気に入りの機能たち (docker向け)

Redisを設定しましょうpublic void ConfigureServices(IServiceCollection services){

var conn = Configuration["REDIS_CONNECTION_STRING"];

var redis = ConnectionMultiplexer.Connect(conn);

services.AddDataProtection().PersistKeysToRedis(redis, "DataProtection-Keys");

services.AddDistributedRedisCache(option =>{

option.Configuration = conn;option.InstanceName = "master";

});services.AddSession();

}

httpsession.redis.cache.windows.net:6380,password=<password>,ssl=True,abortConnect=False

Page 36: ASP.NET Core のお気に入りの機能たち (docker向け)
Page 37: ASP.NET Core のお気に入りの機能たち (docker向け)

BlogTemplateを題材にしてみますASP.NET Coreで作られたブログテンプレート◦ MSDN Blogで紹介

Welcome to the New Blog Template for ASP.NET Developers◦ブログのデータはFilesystem上にxmlファイルとして配置するので、

EF Coreは認証まわりで利用するのみ

修正する必要はあるけどクロスプラットフォームで動きます◦ Local SQLServer SQLite◦ https://github.com/VenusInterns/BlogTemplate/issues/187◦ SQL Server on Linuxでもいいけど同じ1ファイルベースで扱えるので

◦ファイルパスがWindows Style前提なのを共通化◦ https://github.com/VenusInterns/BlogTemplate/issues/188

Page 38: ASP.NET Core のお気に入りの機能たち (docker向け)

EF Coreで必要なコードEntity (DBテーブルに対応する)クラス

DBContextクラス

Startupで接続先やDBの種類などをセットアップ

必要なところでDI経由で取得

Page 39: ASP.NET Core のお気に入りの機能たち (docker向け)

コードからDBテーブル作ろう必要な操作◦コードはあらかじめ用意しておく

◦接続先情報も渡している状態◦ 環境変数やファイルから読む場合はアクセスできるように

◦ migrationコードを生成する

◦ [ここまで開発環境で生成しておいて、ビルド・展開する]

◦ dotnetコマンドで起動する前にupdateを実行する

$ dotnet ef database update

$ dotnet ef migrations add [好きな名前]

Page 40: ASP.NET Core のお気に入りの機能たち (docker向け)

Development環境だとブラウザから実行できたりする

Page 41: ASP.NET Core のお気に入りの機能たち (docker向け)

おまけ:RDBはコンテナ上で動かすべき?コンテナで動かすことがメリットになるなら動かそう

コンテナのメリット => 生成・破棄が簡単。再現性がある

CI/CDでのテストやデモ用

自動復帰できればサービス断がある程度許せるアプリ(コンテナのHealth Checkがあれば容易に復旧できる場合)

CPUやメモリを専有したい場合や、クラスタリング組む場合は従来の方法がいいのでは?

Page 42: ASP.NET Core のお気に入りの機能たち (docker向け)

まとめVisual Studio Docker Support◦ いろいろ進化中

◦ kubernetes対応進むと嬉しいなあ |ω・)チラ

設定の注入◦ Volumeとか環境変数経由で注入できる機能がある

◦ のでご利用のツールの機能と併せて使いましょう

セッション管理◦ セッションデータの格納先とASP.NET Core側の設定に注意

EF Core◦ コードファーストもあります

◦ RDBもコンテナに置いているときは、コードファーストで初期化できるのは便利かも