しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

Docker Compose と Kudu を使って ConoHa 上に ASP.NET Core のデプロイ環境を作ってみた

App Service on Linux 向けとしてですが、Kudu の Mono 対応が進んでいたので Azure 以外の Linux 環境でも動くのではないかと思ったので、手軽な ConoHa を使って試してみました。

そしてついでなので、ASP.NET Core アプリケーションをデプロイするところまで作ってみました。構成は以下のように非常にシンプルですが、地味にめんどくさかったです。

  • リバースプロキシ (nginx)
    • ASP.NET Core アプリケーション
  • Kudu (FastCGI + nginx)

Kudu を動かす部分は App Service on Linux では Apache 2.4 と mod_mono を使っていますが、リポジトリをプッシュする時に問題が出るので nginx と FastCGI を使うように変えました。

Docker Compose の定義を出した方が分かりやすそうなので、貼り付けておきます。

version: '2'

services:
  proxy:
    build: ./proxy
    restart: always
    ports:
      - "80:80"

  aspnetcore:
    build: ./aspnetcore
    restart: always
    depends_on:
      - "proxy"
    volumes:
      - "/var/www/home:/home"

  kudu:
    build: ./kudu
    restart: always
    ports:
      - "8080:80"
    volumes:
      - "/var/www/home:/home"
    environment:
      - WEBSITE_SITE_NAME=conoha
      - KUDU_RUN_USER=conoha

作成した Dockerfile や設定などは GitHub で公開しているので省略します。

/var/www/home を作成しておいて、コンテナでは /home としてマウントします。この home ディレクトリの構成は App Service と同じように作成しておきます。

最低限 wwwroot と LogFiles があれば問題なさそうです。権限周りも一緒に変えておきます。

mkdir -p /var/www/home/site/wwwroot
mkdir -p /var/www/home/LogFiles

chown -R nobody:nogroup /var/www/home
chmod -R 777 /var/www/home

このリポジトリを ConoHa で作成した Ubuntu 16.04 のサーバーに持っていって、イメージのビルドと起動を行います。当然ながら Docker と Dokcer Compose が必要です。

docker-compose.yml があるディレクトリで docker-compose コマンドを叩くだけです。

docker-compose build
docker-compose up -d

これだけで必要なコンテナが全て起動します。書き忘れてましたが 80 と 8080 は開放しておきます。

f:id:shiba-yan:20161217192713p:plain

ちなみに nginx と fastcgi-mono-server4 を立ち上げるために supervisor を使っています。

起動したか確認するために、まず Kudu にアクセスしてみます。IP アドレスとポート番号で見れます。

f:id:shiba-yan:20161217192849p:plain

この時点で Kudu の LocalGit 機能が使えるようになっているので、Source control info API から Git URL を確認できます。ポート番号が入っていないですが、この辺りは対応がめんどくさそうなので放置です。

余談ですが /deploy の URL を GitHub に Webhook として登録すると、GitHub への git push 時に自動でデプロイを実行させることもできます。App Service と全く同じですね。

f:id:shiba-yan:20161217194841p:plain

git clone したリポジトリに対してファイルを追加して git push すると、App Service と同じように KuduScript によってデプロイスクリプトが作成されて、KuduSync で wwwroot にファイルがコピーされます。

ASP.NET Core アプリケーションを実行するためには、dotnet コマンドを使ってビルドしないといけないので、カスタムデプロイスクリプトを追加して対応しました。以下のような感じです。

# 1. Restore nuget packages
dotnet restore

# 2. Build and publish
dotnet publish "src/WebApplication" --output "$DEPLOYMENT_TEMP" --configuration Release

# 3. KuduSync
if [[ "$IN_PLACE_DEPLOYMENT" -ne "1" ]]; then
  "$KUDU_SYNC_CMD" -v 50 -f "$DEPLOYMENT_TEMP" -t "$DEPLOYMENT_TARGET" -n "$NEXT_MANIFEST_PATH" -p "$PREVIOUS_MANIFEST_PATH" -i ".git;.hg;.deployment;deploy.sh"
  exitWithMessageOnError "Kudu Sync failed"
fi

KuduScript が bash と ASP.NET Core の組み合わせに対応していないので、プロジェクトのパスを決め打ちにしています。本来なら KuduScript によって自動的に決定される部分です。

実際に git push してみると、ちゃんと dotnet restore と publish が走っていることが確認できます。

f:id:shiba-yan:20161217195424p:plain

本来ならデプロイスクリプトで Docker のイメージを作成して、それを起動するべきなんでしょうが、コンテナの入れ替えがめんどくさそうだったので App Service と同じように /home/site/wwwroot にビルド済みのアプリケーションをコピーする形にしました。

そして aspnetcore コンテナが /home/site/wwwroot に置かれたアプリケーションを実行する形になっています。今の App Service 同じような仕組みで割と単純に出来ました。

f:id:shiba-yan:20161217192918p:plain

これで nginx にアクセスすると ASP.NET Core で作成したページが返ってきます。

アプリケーションを修正する場合も git push すればビルドされて wwwroot にコピーされますが、aspnetcore コンテナの再起動が必要なので少し面倒です。Kudu のコンテナから docker を使えるようにすると restart が簡単ですが、それは今後の課題ということにします。