AWS CloudShell に .NET 5 をインストールして、Windows向けの実行ファイルを作ってみる

# はじめに
AWS CloudShellはAWSのマネジメントコンソール上で、Amazon Linux2を起動してAWSの各機能をコマンドラインベースで実行するための機能です。Amazon Linux2はCentOS7に近い環境なので、yumを使って.NET Coreをインストールすることができます。

今回はAWS CloudShell上に.NET 5をインストールして、アプリをビルド→実行→Windows向けの実行ファイルのダウンロードをしてみます。
\# だれがうれしいんだ！？という内容ですが、、、

# CloudShellの起動と.NET Core5のインストール
AWS マネジメントコンソールにログインして `>_` なアイコンをクリックしてCloudShellを立ち上げます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/dae5c777-f165-3d44-867d-68cb4b8871c4.png)

あとは、[CentOS に .NET SDK または .NET ランタイムをインストールする](https://docs.microsoft.com/ja-jp/dotnet/core/install/linux-centos)の、[CentOS7](https://docs.microsoft.com/ja-jp/dotnet/core/install/linux-centos#centos-7-)向けの手順を実行してセットアップしていきます。
まずはリポジトリにMicrosoftのリポジトリを追加して

``` sh:CloudShell
$ sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm
Retrieving https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm
warning: waiting for transaction lock on /var/lib/rpm/.rpm.lock
Preparing...                          ################################# [100%]
Updating / installing...
   1:packages-microsoft-prod-1.0-1    ################################# [100%]
```

インストールを実行すると、実際にパッケージをダウンロードするタイミングと、インストールの前に確認を求められるので両方とも`y`で応答するればインストールは完了です。

``` sh:CloudShell
$  sudo yum install dotnet-sdk-5.0
Loaded plugins: ovl, priorities
packages-microsoft-com-prod                                               | 3.0 kB  00:00:00     
packages-microsoft-com-prod/primary_db                                    | 278 kB  00:00:00     
Resolving Dependencies
--> Running transaction check
---> Package dotnet-sdk-5.0.x86_64 0:5.0.101-1 will be installed
--> Processing Dependency: netstandard-targeting-pack-2.1 >= 2.1.0 for package: dotnet-sdk-5.0-5.0.101-1.x86_64
--> Processing Dependency: dotnet-runtime-5.0 for package: dotnet-sdk-5.0-5.0.101-1.x86_64
--> Processing Dependency: dotnet-targeting-pack-5.0 for package: dotnet-sdk-5.0-5.0.101-1.x86_64
--> Processing Dependency: dotnet-apphost-pack-5.0 for package: dotnet-sdk-5.0-5.0.101-1.x86_64
--> Processing Dependency: aspnetcore-runtime-5.0 for package: dotnet-sdk-5.0-5.0.101-1.x86_64
--> Processing Dependency: aspnetcore-targeting-pack-5.0 for package: dotnet-sdk-5.0-5.0.101-1.x86_64
--> Running transaction check
---> Package aspnetcore-runtime-5.0.x86_64 0:5.0.1-1 will be installed
---> Package aspnetcore-targeting-pack-5.0.x86_64 0:5.0.0-1 will be installed
---> Package dotnet-apphost-pack-5.0.x86_64 0:5.0.1-1 will be installed
---> Package dotnet-runtime-5.0.x86_64 0:5.0.1-1 will be installed
--> Processing Dependency: dotnet-hostfxr-5.0 >= 5.0.1 for package: dotnet-runtime-5.0-5.0.1-1.x86_64
--> Processing Dependency: dotnet-runtime-deps-5.0 >= 5.0.1 for package: dotnet-runtime-5.0-5.0.1-1.x86_64
---> Package dotnet-targeting-pack-5.0.x86_64 0:5.0.0-1 will be installed
---> Package netstandard-targeting-pack-2.1.x86_64 0:2.1.0-1 will be installed
--> Running transaction check
---> Package dotnet-hostfxr-5.0.x86_64 0:5.0.1-1 will be installed
--> Processing Dependency: dotnet-host >= 5.0.1 for package: dotnet-hostfxr-5.0-5.0.1-1.x86_64
---> Package dotnet-runtime-deps-5.0.x86_64 0:5.0.1-1 will be installed
--> Running transaction check
---> Package dotnet-host.x86_64 0:5.0.1-1 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

=================================================================================================
 Package                           Arch      Version        Repository                      Size
=================================================================================================
Installing:
 dotnet-sdk-5.0                    x86_64    5.0.101-1      packages-microsoft-com-prod     80 M
Installing for dependencies:
 aspnetcore-runtime-5.0            x86_64    5.0.1-1        packages-microsoft-com-prod    8.0 M
 aspnetcore-targeting-pack-5.0     x86_64    5.0.0-1        packages-microsoft-com-prod    2.1 M
 dotnet-apphost-pack-5.0           x86_64    5.0.1-1        packages-microsoft-com-prod    4.6 M
 dotnet-host                       x86_64    5.0.1-1        packages-microsoft-com-prod     64 k
 dotnet-hostfxr-5.0                x86_64    5.0.1-1        packages-microsoft-com-prod    170 k
 dotnet-runtime-5.0                x86_64    5.0.1-1        packages-microsoft-com-prod     29 M
 dotnet-runtime-deps-5.0           x86_64    5.0.1-1        packages-microsoft-com-prod    2.8 k
 dotnet-targeting-pack-5.0         x86_64    5.0.0-1        packages-microsoft-com-prod    3.1 M
 netstandard-targeting-pack-2.1    x86_64    2.1.0-1        packages-microsoft-com-prod    2.1 M

Transaction Summary
=================================================================================================
Install  1 Package (+9 Dependent packages)

Total download size: 129 M
Installed size: 369 M
Is this ok [y/d/N]: y
Downloading packages:
warning: /var/cache/yum/x86_64/2/packages-microsoft-com-prod/packages/aspnetcore-targeting-pack-5.0.0.rpm: Header V4 RSA/SHA256 Signature, key ID be1229cf: NOKEY
Public key for aspnetcore-targeting-pack-5.0.0.rpm is not installed
(1/10): aspnetcore-targeting-pack-5.0.0.rpm                               | 2.1 MB  00:00:00     
(2/10): dotnet-apphost-pack-5.0.1-x64.rpm                                 | 4.6 MB  00:00:00     
(3/10): dotnet-host-5.0.1-x64.rpm                                         |  64 kB  00:00:00     
(4/10): dotnet-hostfxr-5.0.1-x64.rpm                                      | 170 kB  00:00:00     
(5/10): aspnetcore-runtime-5.0.1-x64.rpm                                  | 8.0 MB  00:00:01     
(6/10): dotnet-runtime-deps-5.0.1-centos.7-x64.rpm                        | 2.8 kB  00:00:00     
(7/10): dotnet-runtime-5.0.1-x64.rpm                                      |  29 MB  00:00:01     
(8/10): dotnet-targeting-pack-5.0.0-x64.rpm                               | 3.1 MB  00:00:00     
(9/10): netstandard-targeting-pack-2.1.0-x64.rpm                          | 2.1 MB  00:00:00     
(10/10): dotnet-sdk-5.0.101-x64.rpm                                       |  80 MB  00:00:09     
-------------------------------------------------------------------------------------------------
Total                                                             11 MB/s | 129 MB  00:00:11     
Retrieving key from https://packages.microsoft.com/keys/microsoft.asc
Importing GPG key 0xBE1229CF:
 Userid     : "Microsoft (Release signing) <gpgsecurity@microsoft.com>"
 Fingerprint: bc52 8686 b50d 79e3 39d3 721c eb3e 94ad be12 29cf
 From       : https://packages.microsoft.com/keys/microsoft.asc
Is this ok [y/N]: y
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Warning: RPMDB altered outside of yum.
  Installing : dotnet-targeting-pack-5.0-5.0.0-1.x86_64                                     1/10 
  Installing : aspnetcore-targeting-pack-5.0-5.0.0-1.x86_64                                 2/10 
  Installing : dotnet-host-5.0.1-1.x86_64                                                   3/10 
  Installing : dotnet-hostfxr-5.0-5.0.1-1.x86_64                                            4/10 
  Installing : dotnet-runtime-deps-5.0-5.0.1-1.x86_64                                       5/10 
  Installing : dotnet-runtime-5.0-5.0.1-1.x86_64                                            6/10 
  Installing : aspnetcore-runtime-5.0-5.0.1-1.x86_64                                        7/10 
  Installing : netstandard-targeting-pack-2.1-2.1.0-1.x86_64                                8/10 
  Installing : dotnet-apphost-pack-5.0-5.0.1-1.x86_64                                       9/10 
  Installing : dotnet-sdk-5.0-5.0.101-1.x86_64                                             10/10 
This software may collect information about you and your use of the software, and send that to Microsoft.
Please visit http://aka.ms/dotnet-cli-eula for more information.
Welcome to .NET!
---------------------
Learn more about .NET: https://aka.ms/dotnet-docs
Use 'dotnet --help' to see available commands or visit: https://aka.ms/dotnet-cli-docs

Telemetry
---------
The .NET tools collect usage data in order to help us improve your experience. It is collected by Microsoft and shared with the community. You can opt-out of telemetry by setting the DOTNET_CLI_TELEMETRY_OPTOUT environment variable to '1' or 'true' using your favorite shell.

Read more about .NET CLI Tools telemetry: https://aka.ms/dotnet-cli-telemetry

Configuring...
--------------
A command is running to populate your local package cache to improve restore speed and enable offline access. This command takes up to one minute to complete and only runs once.
  Verifying  : dotnet-hostfxr-5.0-5.0.1-1.x86_64                                            1/10 
  Verifying  : dotnet-apphost-pack-5.0-5.0.1-1.x86_64                                       2/10 
  Verifying  : aspnetcore-targeting-pack-5.0-5.0.0-1.x86_64                                 3/10 
  Verifying  : netstandard-targeting-pack-2.1-2.1.0-1.x86_64                                4/10 
  Verifying  : dotnet-runtime-5.0-5.0.1-1.x86_64                                            5/10 
  Verifying  : aspnetcore-runtime-5.0-5.0.1-1.x86_64                                        6/10 
  Verifying  : dotnet-targeting-pack-5.0-5.0.0-1.x86_64                                     7/10 
  Verifying  : dotnet-sdk-5.0-5.0.101-1.x86_64                                              8/10 
  Verifying  : dotnet-runtime-deps-5.0-5.0.1-1.x86_64                                       9/10 
  Verifying  : dotnet-host-5.0.1-1.x86_64                                                  10/10 

Installed:
  dotnet-sdk-5.0.x86_64 0:5.0.101-1                                                              

Dependency Installed:
  aspnetcore-runtime-5.0.x86_64 0:5.0.1-1         aspnetcore-targeting-pack-5.0.x86_64 0:5.0.0-1
  dotnet-apphost-pack-5.0.x86_64 0:5.0.1-1        dotnet-host.x86_64 0:5.0.1-1                  
  dotnet-hostfxr-5.0.x86_64 0:5.0.1-1             dotnet-runtime-5.0.x86_64 0:5.0.1-1           
  dotnet-runtime-deps-5.0.x86_64 0:5.0.1-1        dotnet-targeting-pack-5.0.x86_64 0:5.0.0-1    
  netstandard-targeting-pack-2.1.x86_64 0:2.1.0-1

Complete!
```
.NET 5がインストールされました。

``` sh:CloudShell
$ dotnet --version
5.0.101
```

# ビルドしてWindows向けの実行ファイルをダウンロードする

Console アプリを作成して実行してみる。

``` sh:CloudShell
$ mkdir consoleapp
$ cd consoleapp
$ dotnet new console
$ dotnet run
Hello World!
```

Program.csを開き、

``` sh:CloudShell
$ ls
bin  obj  Program.cs  sample.csproj
$ vi Program.cs 
```

まぁ、よくある修正をして保存後、

``` Program.cs
using System;
  
namespace sample
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello CloudShell");
        }
    }
}
```

ビルドして実行すると反映されましたね。

``` sh:CloudShell
$ dotnet run
Hello CloudShell
```

Windows 向けにビルドします。

``` sh:CloudShell
$ dotnet publish -r win-x86 -c Release -p:PublishSingleFile=true
Microsoft (R) Build Engine version 16.8.0+126527ff1 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  All projects are up-to-date for restore.
  sample -> /home/cloudshell-user/sample/bin/Release/net5.0/win-x86/sample.dll
  sample -> /home/cloudshell-user/sample/bin/Release/net5.0/win-x86/publish/
```

出来上がったファイルをtarで固めてダウンロードします。

``` sh:CloudShell
$ cd /home/cloudshell-user/sample/bin/Release/net5.0/win-x86/
$ tar cvfz ~/app.tar.gz publish/
publish/
publish/sample.exe
publish/mscordaccore.dll
publish/clrjit.dll
publish/clrcompression.dll
publish/sample.pdb
publish/coreclr.dll
```

Actions → Download fileでファイルをダウンロードできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/9f4f03a9-fbd5-c5bd-f610-7b10e8b68472.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/0593773e-c59a-d06f-60ae-3fe3f5bce317.png)

Windowsで実行してみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/472955e2-d3b5-3cb7-8ab7-c5ae0b30a4d9.png)
動きましたね！

# まとめ
- AWS CloudShell上でも入れれば.NET動くよ
- .NET のクロスコンパイラでWindows、Macの実行ファイルを作成できるよ
- ビルド方法によっては.NET ランタイムがインストールされていなくても動作するよ

CloudShellでは永続化されるのはHomeディレクトリ配下の1GBのファイルだけで、他は起動するたびに失われるので最初からインストールされているランタイムを使ったほうが良いですよね。PowerShell Coreも入っていますし。