Upload
takayoshi-tanaka
View
636
Download
1
Embed Size (px)
Citation preview
(主にdocker向けの)ASP.NET Coreの
お気に入りの機能たち@tanaka_733
2017年10月23日 Fukuoka.NET Conf 2017
自己紹介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
今日のセッションのゴールDockerをはじめとしたコンテナ環境でASP.NET Coreを便利に使いたい
そんな時に役立つ機能のご紹介
※kubernetes (OpenShift)の機能とあわせて紹介していますが、他のオーケストレーションツール/サービスでも同じような機能があるはずですkubectl: kubernetsコマンド, oc: OpenShiftクライアントコマンド
Agenda
◦Visual StudioでのDocker support
◦外部ファイルを使った設定の注入
◦複数コンテナでのセッション管理
◦リモートデバッグ
◦EF Core: コードファースト DB migration
Docker Support◦ ASP.NET Core プロジェクトのテンプレート選択画面
Docker Support◦ ASP.NET Core プロジェクトのテンプレート選択画面
テンプレートによっては利用できない
Windows/Linuxコンテナ選択可 ソリューションフォルダを作らないと
うまく動作しない(バージョンがあった)
何が起きるのか?◦Dockerfileの追加
◦単純なASP.NET Coreアプリのコンテナだったのが15.5 Previewではちょっと手の込んだ方法に…
◦docker-composeプロジェクトの追加
◦ docker composerファイルの追加
◦ローカルのdockerへの配置とデバッグの支援
◦機能自体はVisual Studio SDK側で実装されている
◦ Linux/Windowsコンテナの選択はdocker-composeプロジェクトで設定してある
新しい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"]
Docker imageの生成フロー
microsoft/aspnetcore:2.0
base
port80
microsoft/aspnetcore-build:2.0
build
final
port80entrypoint
solutionをコピーbuild
publish
publish
バイナリをコピー
何がうれしい?◦最終的なコンテナサイズが小さくなった
◦今までは.NET Core SDK (Runtime+ビルドに必要なもの)をベースにしていたので、最初からサイズがでかい
◦Runtimeのみのコンテナではビルドできない
◦ビルド用のコンテナを別にして、そちらはSDKこみで。最終的な成果物のコンテナはRuntimeのみにした
◦(おまけ)OpenShiftもTemplateとして提供していますセッション後のハイパー宣伝タイムで!
Dockerデバッグの仕組み
Docker for Windows
Hyper-V
Docker用仮想マシン
コンテナ実行用軽量LinuxVM
Docker Engine Docker クライアント
Linuxコンテナプロセス
デバッグ用コンテナ起動
Hyper-V
コンテナ実行用軽量LinuxVM
ホストOS(Windows)とファイル共有
vsdbgバイナリなど(Cドライブ)
プロジェクトファイル(保存場所のドライブ)tail -f /dev/null
で起動しっぱなし
その他NuGetパッケージなどもファイル共有
ビルド
Hyper-V
コンテナ実行用軽量LinuxVM Windows側でプロジェクトをビルド
tail -f /dev/nullで起動しっぱなし
app.dll
デバッグ開始
Hyper-V
コンテナ実行用軽量LinuxVM
dotnet app.dll
tail -f /dev/nullで起動しっぱなし
app.dll
./vsdbg vsdbg
コンテナ内でdotnetプロセスを開始デバッガープロセス開始SSHこしにリモートデバッグ接続
(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
.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
.NET CoreのDebuggerの特徴◦低レイヤーはwindbg(vsdbg?)、GDB/LLDBとOS固有
◦WindowsではVisual Studioがすべて面倒みてくれる
◦Linux (Mac)ではMIEngineというツールが面倒をみる
◦ MS製OSSだけど、バイナリの利用はVS製品のみ許可
◦ツールは違えどインターフェースは共通
◦WindowsとLinux(Mac)の間で相互にリモートデバッグが可能
リモートのDockerに接続したい◦技術的には可能
◦ vsdbgのバイナリを手動インストール (VSから使う用途はOKのはず)
◦ sshコマンドの代わりにkubectl exec/oc rshなどを使えばよい
◦が、現状、機能としては存在しない
◦クローズド部分なのでVSIX(VS拡張)も作れない模様
◦Azureはkubernetes推しなので、将来対応するのでは?
◦ composerを直接はサポートしていないのでそこも対応を期待
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}"}
}
設定ファイルの取り扱い◦ソースコード=バイナリを変更せずに、設定ファイルの差し替えで動作を変更したい
◦Docker環境でどうやって外部ファイルを注入する?◦1回アプリのコンテナイメージ作ったら、設定ファイルの変更だけのためにイメージ作り直したくないですよね?
Add***File メソッドで設定の注入
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
機密情報を扱いたい場合◦DBのパスワードなど◦ソースコードリポジトリには入れたくない
◦アプリのコンテナイメージにも入れておきたくない
◦ASP.NET CoreのUserSecret機能は開発用途なので使うべきではない◦マシン固有の暗号キーでファイルに保存しておく機能
◦Azureの場合 Azure Key Vault と Managed Service Identity◦ 今のところPreviewでApp ServiceとAzure Functionsのみ利用可
◦ kubernetes/OpenShiftの場合 Secret機能
Secret機能Base64エンコードした値を格納して、dockerコンテナにファイルもしくは環境変数としてマウント◦暗号化ではない。アクセスを制限できるという意味合いはある
複数コンテナでHTTPセッションデフォルトでは:◦コンテナごとにHTTPセッションをメモリ内に格納◦コンテナでない場合もプロセスごとに別々
つまり?◦コンテナへのロードバランシングがStickyセッションならコンテナが生きている限り問題なし
◦コンテナが死んだらセッションが維持できない◦ Stickyじゃないとそもそもセッションが維持できない
container A
cnotainer B
container C
ASP.NET Core
ASP.NET Core
ASP.NET Core
それぞれのコンテナに別々にセッションデータが格納される
container AでHTTPセッション確立しても次のHTTPリクエストがcontainer Bだと確立したセッションの情報はない
IDistributedCache & IDataProtectionIDistributedCache◦ 名前からしてこれだけ設定すれば十分な気がするこれがまちがい◦ 分散キャッシュを提供◦ セッションの格納先に指定できる◦ SQLServerとRedisを保存先とするライブラリASP.NET Coreチームが提供
IDataProtection◦ 暗号化のキー管理を提供◦ HTTPセッションの暗号化にも利用されている◦ デフォルトではコンテナ(マシン)ごとにキーを発行し、ローカルファイルに保存
◦ Network FilesystemとRedisとAzure Storage, Azure Fileを提供
container A
container B
container C
ASP.NET Core
ASP.NET Core
ASP.NET Core
Session Data A’
containerごとに異なるキーセッションデータ自体を共有できても、キーが違うので復号できず意味がない
~/.aspnet
IDistributedCacheをRedisに設定するだけだと…
machine A
machine B
machine C
ASP.NET Core
ASP.NET Core
ASP.NET Core
Session Data
IDataProtectionもRedisに設定
キー自体をRedisに保存して共有するのでOK!Redisが死んだ場合の考慮は必要
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
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
EF Coreで必要なコードEntity (DBテーブルに対応する)クラス
DBContextクラス
Startupで接続先やDBの種類などをセットアップ
必要なところでDI経由で取得
コードからDBテーブル作ろう必要な操作◦コードはあらかじめ用意しておく
◦接続先情報も渡している状態◦ 環境変数やファイルから読む場合はアクセスできるように
◦ migrationコードを生成する
◦ [ここまで開発環境で生成しておいて、ビルド・展開する]
◦ dotnetコマンドで起動する前にupdateを実行する
$ dotnet ef database update
$ dotnet ef migrations add [好きな名前]
Development環境だとブラウザから実行できたりする
おまけ:RDBはコンテナ上で動かすべき?コンテナで動かすことがメリットになるなら動かそう
コンテナのメリット => 生成・破棄が簡単。再現性がある
CI/CDでのテストやデモ用
自動復帰できればサービス断がある程度許せるアプリ(コンテナのHealth Checkがあれば容易に復旧できる場合)
CPUやメモリを専有したい場合や、クラスタリング組む場合は従来の方法がいいのでは?
まとめVisual Studio Docker Support◦ いろいろ進化中
◦ kubernetes対応進むと嬉しいなあ |ω・)チラ
設定の注入◦ Volumeとか環境変数経由で注入できる機能がある
◦ のでご利用のツールの機能と併せて使いましょう
セッション管理◦ セッションデータの格納先とASP.NET Core側の設定に注意
EF Core◦ コードファーストもあります
◦ RDBもコンテナに置いているときは、コードファーストで初期化できるのは便利かも