ASP.NET Core 3.1のREST-APIをVisualStudio2019とDockerでHerokuにデプロイする手順

## はじめに

#### 背景

ASP.NET Coreを社内で啓蒙しようとした際、ちょうどいい記事が見つからなかったので、投稿しておきます。

#### 前提

「ゼロからの初心者が、最初のデプロイを成功させるまで」の説明をします。
但し、Herokuアカウントが必要です。またHeroku CLIを端末にインストールしておいてください。

* Visual Studio 2019を使用します。持っていない方のためにインストール手順を後述します。なお、無償のCommunity Editionを利用される場合は、使用権に制限があるのでライセンス条項を読みましょう。但しこの記事の内容を個人で作成する分には、個人ライセンスが適用されますので問題ありません。
* 開発環境は、この記事においてはWindows10 + Visual Studio 2019に限定します。for MacやVisualStudio Codeでもできるはずですが、今回の趣旨に合わないので割愛させてください。
* 執筆時点で最新のLTSである.Net Core 3.1を使用します。

## 準備

#### Visual Studio 2019 をインストールしよう

* Visual Studio 2019がインストールされていなければ、インストールしてください。

* Visual Studio 2019に「ASP.NETとWeb 開発」のワークロードがセットアップされていなければ、セットアップしてください。

上記の前提の環境を作成するために、よければ以下の記事を参考にしてください。
[ASP.NET Coreを利用するためのVisual Studio 2019のインストール方法](https://qiita.com/kami_teru/items/49d95194bcb4836b591e)

#### Docker Desktopをインストールしよう

* Windows 10 Homeの人は、この手順は省略してください。(Hyper-Vの有効化ができないため)

ただしDocker Desktopのインストール手順は割愛します。
ざっくり書くと、以下の手順になります。

* Hyper-Vの有効化(有効化後、端末の再起動が必要です)
* Docker Hubへのサインアップ
* Docker Desktop for Windows のインストール
* ↑インストールの際、`Use Windows containers instead of Linux containers`のチェックは不要です。
(Azureへもlinuxベースのコンテナでデプロイできるため)

なお、以下のページの手順がわかりやすかったです。よければご参照ください。
[【入門】はじめての Docker Desktop for Windows のインストールと CentOS の仮想環境構築のセットアップ](https://qiita.com/gahoh/items/7b21377b5c9e3ffddf4a)

# さぁ、はじめよう

## ASP.NET Core 3.1のREST-APIプロジェクトを作成しよう

ASP.NET Core 3.1のREST-APIプロジェクトは、以下の構成を選択してプロジェクトを作成します。
* プロジェクトテンプレート: ASP.NET Core Web アプリケーション
* プロジェクトの構成: API

プロジェクトの作成方法の詳細は、以下の記事を参考に進めてみてください。
[ASP.NET Core(C#)とVisualStudio2019でREST-APIを開発するためのプロジェクト作成方法](https://qiita.com/kami_teru/items/1883c4f4cf16256d4646)

プロジェクト名／ソリューション名は、まだ特にアイディアがなければ、MyHelloServiceとでもしておきましょう。

↓上記の手順が完了すると、以下の状態になります。
![MyHelloService - Microsoft Visual Studio 2020_02_15 17_49_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/378d6ef7-ff0e-205d-b6cd-0e6917ffd520.png)

## ASP.NET Core 3.1のREST-APIプロジェクトをデバッグしてみよう

### いきなり動かしてみる

さっそく、MyHelloServiceをデバッグしてみましょう。テンプレートから作成したプロジェクトは、そのままでも動作するようになっています。

デバッグする方法は、2種類。
* IIS Expressで動作させて、デバッガをアタッチする
* Kestrelで動作させて、デバッガをアタッチする

> Kestrel は、ASP.NET Core 向けのクロスプラットフォーム Web サーバーです
--引用：[ASP.NET Core への Kestrel Web サーバーの実装](https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-3.1)

とのことなので、今回はこちらを使いましょう。

↓「IIS Express」ボタンの右端にある「▼」をクリックし、「MyHelloService」を選択します。
![スクリーンショット (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/6445b587-39df-5b66-f348-05c440b0a362.png)

↓どうやらこのプロジェクトはデフォルトでSSLが有効になっているようです。「はい」を選んであげましょう。
![スクリーンショット (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/060d327d-287b-d66a-1511-8bdb13536ca7.png)

↓Windowsがセキュリティ警告を発しますが、「はい」を選んであげましょう。
![スクリーンショット (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/08de3098-7bdd-6eb7-496c-84911e1018b5.png)

するとどうでしょう。ブラウザが開き、5日間のお天気情報が表示された・・・だと・・・！？
↓うだるような暑さ・・・？
![Microsoft Edge 2020_02_15 19_00_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/945ece56-8311-ea1d-bd53-4eef1729eb15.png)

これはテンプレートが、サンプルコード`WeatherForecastController` を含んでいるからですね。
↓なお、お天気情報は実際のものではなくランダムに表示されている。
![MyHelloService - Microsoft Visual Studio 2020_02_15 18_12_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/3a73ef13-24fd-6ff2-61a8-013ca767612d.png)

以上が、最もシンプルなコードのデバッグ方法です。
しかしそれは、「開発環境では動作します」というレベルに過ぎないので、心許ないですね。

そこで、第3の選択肢。
* Dockerコンテナ内で動作させて、デバッガをアタッチする

その方法を、紹介します。
※Windows 10 Homeの方は、できない手順になりますので、
　「ASP.NET Core 3.1のREST-APIプロジェクトをHerokuにデプロイしよう」
　まで読み飛ばしてください。

### より実行環境に近い、Dockerコンテナ内で動かす

#### 1) プロジェクトにDockerコンテナの構成ファイル(Dockerfile)を追加する

Dockerコンテナの構成ファイル(Dockerfile)は、VisualStudio2019の機能で作成することができます。

そのためには、以下の手順を行いましょう。
↓「プロジェクトを右クリック」＞「追加」＞「Dockerサポート」を選択。
![スクリーンショット (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/b52538dc-934e-5967-e426-c3033cddfb32.png)

↓すると、次のようなDockerFileが作成されます。
![スクリーンショット (19).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/0ffa594f-285e-c8ad-65d4-f5292560b8bc.png)

#### 2) Dockerコンテナの構成ファイル(Dockerfile)をHeroku用に修正する

作成されたDockerfileは、Microsoft Azureに発行する際はそのまま使えるのですが、
Herokuに発行する際は少し手を加える必要があります。

これから紹介する修正内容は、次のブログ記事を参考にさせていただきました。
[Deploy ASP.NET Core 3.1 Web API to Heroku with Docker](https://jakubwajs.wordpress.com/2020/01/31/deploying-asp-net-core-3-1-web-api-to-heroku-with-docker/)

次の`For heroku-container modification`で囲まれた範囲を修正してください。

```dockerfile
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
#-- For heroku-container modification -- START
#COPY ["MyHelloService/MyHelloService.csproj", "MyHelloService/"]
#RUN dotnet restore "MyHelloService/MyHelloService.csproj"
#COPY . .
#WORKDIR "/src/MyHelloService"
COPY ["MyHelloService.csproj", "MyHelloService/"]
RUN dotnet restore "MyHelloService/MyHelloService.csproj"
WORKDIR "/src/MyHelloService"
COPY . .
#-- For heroku-container modification -- END
RUN dotnet build "MyHelloService.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "MyHelloService.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
#-- For heroku-container modification -- START
#ENTRYPOINT ["dotnet", "MyHelloService.dll"]
CMD ASPNETCORE_URLS=http://*:$PORT dotnet MyHelloService.dll
#-- For heroku-container modification -- END
```

#### 3) Dockerを指定してデバッグする

先ほどデバッグする際に選択した「MyHelloService」ボタンの右端にある「▼」をクリックすると、「Docker」が追加されているので、これを実行しましょう。

↓すると、Docker Desctopが、Cドライブへのアクセスを求めてきました。（画像右下の通知を見てください）「Share it」を選択してあげましょう。
![スクリーンショット (20).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/516c6f4d-95f7-eadf-b6d3-0360d0a5d1d3.png)

↓するとどうでしょう。Dockerコンテナ上で動いたっぽい感じになりましたね？
![スクリーンショット (21).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/fdd9dcff-ee2c-8d69-14bf-6a8a3570f243.png)

↓日本語もちゃんと表示できています。
![Microsoft Edge 2020_02_16 17_17_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/155b38ac-cd6a-d46b-7e8b-6ee95a67d3a2.png)

これで、このより実行環境に近い「Dockerコンテナ」でも動作することが確認できました。

ではこれを、いよいよHerokuにデプロイしたいと思います。

## ASP.NET Core 3.1のREST-APIプロジェクトをHerokuにデプロイしよう

### デプロイ先となるHeroku Appを作成する

この作業はコマンドラインでも行えますが、その記事は多数見つかるので、あえてダッシュボードから行きましょう。

↓Herokuのダッシュボードで、Create new app を選択してください。
![Personal apps _ Heroku - Mozilla Firefox 2020_02_16 23_19_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/9628bd9d-7376-8996-493d-b306472a84a6.png)

↓App nameを入力して、「Create app」ボタンをクリックしましょう。
![Personal apps _ Heroku - Mozilla Firefox 2020_02_16 23_22_33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/773b7e0a-dda8-7ab0-b807-a54911a30673.png)

↓すると、作成されたHeroku AppのDeployページが開きます。画像右下の「Container Registry」をクリックしましょう。
![Personal apps _ Heroku - Mozilla Firefox 2020_02_16 23_24_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/c3c89142-8aec-a014-e5b2-be2f2b13dc4e.png)

↓すると、ページ下部に、このHeroku AppにDockerコンテナをDeployするための手順が表示されます。コマンド付きなので、親切ですね！
![Personal apps _ Heroku - Mozilla Firefox 2020_02_16 23_26_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/19736b34-43e8-7f30-ef22-0319901fbba6.png)

これでデプロイ先となるHeroku Appが作成できました。

次はいよいよ、Heroku Appへのデプロイを行います。

### Heroku Appにデプロイする

手順は、Heroku AppのDeployページに書かれている通りの手順で行います。

※Heroku CLIをインストールしていない人は、herokuコマンドを使用するためにインストールが必要です。

以下、Dockerfileが作成されたディレクトリで、コマンドを実行します。

#### 1) herokuにログインする

```
> heroku login
```
#### 2) heroku-containerにログインする

```
> heroku container:login
```
#### 3) プロジェクトとDockerコンテナ構成ファイルをheroku-containerにプッシュする

※`my-hello-service-2020021623200`はあなたのApp名に置き換えて実行してください

```
> heroku container:push web -a my-hello-service-2020021623200
```
このタイミングで、Dockerfileの記述に基づく構成が行われます。
具体的には、ASP.Net Core 3.1実行環境の作成、アプリケーションのビルド、などです。

#### 4) プッシュした内容を、Heroku Appに適用する

※`my-hello-service-2020021623200`はあなたのApp名に置き換えて実行してください

```
> heroku container:release web -a my-hello-service-2020021623200
```
これで、Heroku AppでASP.NET Core 3.1 REST-APIプロジェクトが動作する準備が整いました。
次のコマンドを実行するとブラウザでURLを開くことができます。

#### 5) Heroku AppのURLをブラウザで開く

```
> heroku open -a my-hello-service-2020021623200
```
※ただしアプリケーションパスは指定されないので、開いたURLに`/weatherforecast`を足してあげてくださいね。

なお、このコマンドの手順1と2は、サインインした状態を記憶してくれるので、毎回行う必要はありません。

では最後に少しおまけを。

#より便利に利用するために

便利かどうかはそれぞれの主観によるところですが、まぁこういう使い方もあるよってことで。。。

### Herokuにデプロイするためのコマンドを、Visual Studioに追加する

Visual Studioは、コマンドをメニューに追加することができます。
メニューバーの「ツール」＞「外部ツール」を選択すると開くウィンドウで、以下の入力を行います。

#### 1) heroku container:push コマンドを登録する

↓次のように入力します。
![MyHelloService - Microsoft Visual Studio 2020_02_16 23_51_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/6229b92f-79f2-8d56-9247-5993626d7dd8.png)

#### 2) heroku container:push コマンドを登録する

↓次のように入力します。
![MyHelloService - Microsoft Visual Studio 2020_02_16 23_56_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/6e312d7c-4b3f-c9cd-3bb5-82380398be42.png)

#### 3) heroku open コマンドを登録する

↓次のように入力します。
![MyHelloService - Microsoft Visual Studio 2020_02_16 23_56_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/e6607b18-3304-5ea2-6822-2d76482f7622.png)

### Herokuにデプロイするためのコマンドを、Visual Studioから実行する

↓「出力ウィンドウを使用」を選択するしたことで、VisualStudioだけで結果を確認することができます。
![スクリーンショット (24).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109362/d5387443-288e-04f8-30b0-e2cbf7b71460.png)

# 最後に

この投稿が、マルチターゲットの時代に入った.Netに触れてみるきっかけになれば、幸いです。
また、お読みいただいてわかりにくかった点などありましたら、フィードバックいただけると嬉しいです。