.NET をIBM Powerで動かしてみた話 #3

本".NET をIBM Powerで動かしてみた話"シリーズは、.NET 7がLinux on Power環境で利用可能となった([IBM社のブログ : .NET 7 now includes support for Linux on Power!](https://community.ibm.com/community/user/powerdeveloper/blogs/janani-janakiraman/2022/11/07/net7-support-linux-on-power))ということで、以下のテーマで3つのブログを掲載予定としています。

<b>1. 「本当に.NET 7は問題なく動くのか」
2. 「x86環境で作成された.NET アプリケーションはppc64le環境でもそのまま動くのか」
3. 「コンテナ環境でも利用できるのか」</b>

今回は、3つ目のテーマである"「コンテナ環境でも利用できるのか」" について記載していこうと思います。
なお、本記事で使用している環境は、上記の"1. 「本当に.NET 7は問題なく動くのか」"の記事で作成したものをそのまま使用しています。
まだ読まれていない方は、よろしければ本記事に入る前に以下の内容もご覧ください。また併せて"2. 「x86環境で作成された.NET アプリケーションはppc64le環境でもそのまま動くのか」"もご覧いただけると嬉しいです。

https://qiita.com/Nakaji1106/items/f0761c4d1dce58c0b8d5

https://qiita.com/Nakaji1106/items/7ac09e9579a8b3f271f3

それでは、本題に入っていきたいと思います。

# 3. 「コンテナ環境でも利用できるのか」

結論として、コンテナ環境で.NET 7 をIBM Power上で利用することは可能です。
利用方法は、以下の2点です。

(1) 公開されている.NET 7を含んだコンテナイメージを利用する
(2) ベースのコンテナイメージ(UBI : Red Hat Universal Base Imageなど)に.NET 7アプリケーションをインストールして利用する

今回の記事では、(1)の動作を確認していきたいと思います。(2)の内容は、RHEL環境に.NET 7をインストールできることからも、動作は問題ないのではと思っています。

まず、公開されている.NETコンテナイメージですが、以下のものがあります。
Red Hat Ecosystem Catalogにイメージは公開されています。実際に、.NET(dotNET)コンテナイメージを"ppc64le"版でフィルターした検索結果が以下の図です。

全部で、4つのイメージが表示されました。".NET 7.0 Runtime Only" と".NET 7.0 and Runtime" の2種類に対し、RHEL8ベースのイメージとubi8ベースのイメージの2パターンが準備されていますね。

https://catalog.redhat.com/software/containers/search?q=dotNet&p=1&architecture=ppc64le

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613078/fa6488ef-70bc-4133-01eb-abbf161c3072.png)

早速このコンテナイメージを使用して、.NETのサンプルコードを動かしてみましょう。

#### (a) サンプルコードの内容を理解する

今回ベースにしたサンプルコードは、以下のGitHubの内容です。このサンプルコードでは、.NETの実行環境用コンテナイメージに、手元の.NETのアプリケーションサンプルコードをコピーして、新たなコンテナイメージを作成しています。(Dockerfileを使用したコンテナイメージのビルド作業)

https://github.com/dotnet/dotnet-docker/tree/main/samples/dotnetapp

まずこのサンプルコードで実施している内容を確認していきましょう。以降の内容は、["1. 「本当に.NET 7は問題なく動くのか」"](https://qiita.com/Nakaji1106/items/f0761c4d1dce58c0b8d5)で作成したAlmaLinuxの環境で実施しています。


- 手元の環境に対象のGitHubをクローンします。

```bash: 作業ディレクトリの作成
[root@dotnet-sample-alma87 ~]# pwd
/root
[root@dotnet-sample-alma87 ~]# mkdir container-sample
[root@dotnet-sample-alma87 ~]# cd container-sample/
[root@dotnet-sample-alma87 container-sample]# pwd
/root/container-sample
```

```bash: git cloneの実施
[root@dotnet-sample-alma87 container-sample]# git clone https://github.com/dotnet/dotnet-docker.git
Cloning into 'dotnet-docker'...
remote: Enumerating objects: 80481, done.
remote: Counting objects: 100% (1766/1766), done.
remote: Compressing objects: 100% (495/495), done.
remote: Total 80481 (delta 755), reused 1656 (delta 699), pack-reused 78715
Receiving objects: 100% (80481/80481), 13.93 MiB | 7.13 MiB/s, done.
Resolving deltas: 100% (36647/36647), done.
[root@dotnet-sample-alma87 container-sample]#
[root@dotnet-sample-alma87 container-sample]# ls
dotnet-docker
```

- 使用するサンプルコードの確認

今回は"dotnet-docker/samples/dotnetapp/"に含まれるアプリケーションを使用したいと思います。
このディレクトリには、複数のプラットフォームに対応したDockerfileとアプリケーションコードである"dotnetapp.csproj"や"Program.cs"などが含まれています。

```bash:dotnet-docker/samples/dotnetapp/
[root@dotnet-sample-alma87 container-sample]# cd dotnet-docker/samples/dotnetapp/
[root@dotnet-sample-alma87 dotnetapp]# ls
Dockerfile                    Dockerfile.alpine-arm64-slim  Dockerfile.debian-arm32     Dockerfile.nanoserver-x64       Dockerfile.ubuntu-x64                  Program.cs
Dockerfile.alpine-arm32       Dockerfile.alpine-x64         Dockerfile.debian-arm64     Dockerfile.nanoserver-x64-slim  Dockerfile.ubuntu-x64-slim             README.md
Dockerfile.alpine-arm32-slim  Dockerfile.alpine-x64-slim    Dockerfile.debian-x64       Dockerfile.ubuntu-arm32         Dockerfile.windowsservercore-x64       dotnetapp.csproj
Dockerfile.alpine-arm64       Dockerfile.chiseled           Dockerfile.debian-x64-slim  Dockerfile.ubuntu-arm64         Dockerfile.windowsservercore-x64-slim
```
次に、Dockerfileの中身を確認します。
このDockerfileでは、"mcr.microsoft.com/dotnet/sdk:7.0"のコンテナイメージを使用して対象の.NETアプリケーションをビルドし、コンテナ起動時にはビルドした.NETアプリケーションを起動するコンテナイメージを作成しています。

```bash:dotnet-docker/samples/dotnetapp/Dockerfile
[root@dotnet-sample-alma87 dotnetapp]# cat Dockerfile
# https://hub.docker.com/_/microsoft-dotnet
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /source

# copy csproj and restore as distinct layers
COPY *.csproj .
RUN dotnet restore --use-current-runtime

# copy and publish app and libraries
COPY . .
RUN dotnet publish -c Release -o /app --use-current-runtime --self-contained false --no-restore

# final stage/image
FROM mcr.microsoft.com/dotnet/runtime:7.0
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "dotnetapp.dll"]
```
#### (b) Dockerfileの書き換え

今回は、上記のDockerfileをIBM Power(Linux on Power)用に書き換えます。
変更内容はシンプルで、以下の3箇所を変更します。

・　使用するコンテナイメージをppc64le版のコンテナイメージに書き換え
・　コマンド実行ユーザとして"root"を使用
・"--use-current-runtime" の削除


```bash:変更後のDockerfile
[root@dotnet-sample-alma87 dotnetapp]# cat Dockerfile
# https://catalog.redhat.com/software/containers/ubi8/dotnet-70/633c2b5397360f0e1f503872?container-tabs=overview
FROM registry.access.redhat.com/ubi8/dotnet-70:7.0-5 AS build
WORKDIR /source
USER root

# copy csproj and restore as distinct layers
COPY *.csproj .
RUN dotnet restore 

# copy and publish app and libraries
COPY . .
RUN dotnet publish -c Release -o /app --self-contained false --no-restore

# final stage/image
FROM registry.access.redhat.com/ubi8/dotnet-70:7.0-5
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "dotnetapp.dll"]
```

#### (c) 変更後のDockerfileを使用してイメージをビルド

早速、変更したDockerfileを使用して、.NETアプリケーションが起動するコンテナイメージをビルドしてみましょう。
とその前に、コンテナイメージのビルド時に使用するpodmanコマンドをインストールします。

```bash:podmanコマンドのインストール
[root@dotnet-sample-alma87 dotnetapp]# dnf install -y podman
[root@dotnet-sample-alma87 dotnetapp]# podman --version
podman version 4.2.0
```

今回は、podmanコマンドとしてversion 4.2.0がインストールされました。では、コンテナイメージをビルドしてみます。

```bash:コンテナイメージのビルド
[root@dotnet-sample-alma87 dotnetapp]# podman build -t dotnetapp:ubi8-dotnet7-ppc64le -f Dockerfile
[root@dotnet-sample-alma87 dotnetapp]# podman image list
REPOSITORY                                 TAG                   IMAGE ID      CREATED         SIZE
localhost/dotnetapp                        ubi8-dotnet7-ppc64le  77b9d5054b3a  42 seconds ago  621 MB
<none>                                     <none>                12e47eb52fcb  46 seconds ago  630 MB
registry.access.redhat.com/ubi8/dotnet-70  7.0-5                 2479c7826db9  6 days ago      621 MB
```

このコマンドにより、"localhost/dotnetapp:ubi8-dotnet7-ppc64le"がコンテナイメージとして作成されました。

#### (d) 作成したコンテナイメージを実行

作成したコンテナイメージを実際に起動させてみます。

```bash:podman run の実行
[root@dotnet-sample-alma87 dotnetapp]# podman run localhost/dotnetapp:ubi8-dotnet7-ppc64le
         42                                                    
         42              ,d                             ,d     
         42              42                             42     
 ,adPPYb,42  ,adPPYba, MM42MMM 8b,dPPYba,   ,adPPYba, MM42MMM  
a8"    `Y42 a8"     "8a  42    42P'   `"8a a8P_____42   42     
8b       42 8b       d8  42    42       42 8PP!!!!!!!   42     
"8a,   ,d42 "8a,   ,a8"  42,   42       42 "8b,   ,aa   42,    
 `"8bbdP"Y8  `"YbbdP"'   "Y428 42       42  `"Ybbd8"'   "Y428  

.NET 7.0.1
Red Hat Enterprise Linux 8.7 (Ootpa)

UserName: default
OSArchitecture: Ppc64le
ProcessorCount: 4
TotalAvailableMemoryBytes: 4405985280 (4.00 GiB)
```

問題なく、実行できましたね！

# まとめ

今回は、".NET をIBM Powerで動かしてみた話"の最後として、コンテナ環境版について記載いたしました。
.NETのコンテナは問題なく起動できるとして、そのコンテナ環境上でも.NETアプリケーションを変更なく実行できることも確認できました。

しかし、.NETアプリケーションを組み込んだコンテナイメージの場合、x86環境とppc64le環境とでは、ベースとして使用するコンテナイメージが異なる為、Dockerfileの変更は必要となりました。変更自体は大きな内容ではありませんでしたが、このように各レイヤーでCPUアーキテクチャに依存する箇所があるかどうかをチェックすることは安定稼働のためにも必要だと理解できました。

それでは、今回は以上となります。本記事が何かの参考となれば幸いです。