本".NET をIBM Powerで動かしてみた話"シリーズは、.NET 7がLinux on Power環境で利用可能となった(IBM社のブログ : .NET 7 now includes support for Linux on Power!)ということで、以下のテーマで3つのブログを掲載予定としています。
1. 「本当に.NET 7は問題なく動くのか」
2. 「x86環境で作成された.NET アプリケーションはppc64le環境でもそのまま動くのか」
3. 「コンテナ環境でも利用できるのか」
今回は、3つ目のテーマである"「コンテナ環境でも利用できるのか」" について記載していこうと思います。
なお、本記事で使用している環境は、上記の"1. 「本当に.NET 7は問題なく動くのか」"の記事で作成したものをそのまま使用しています。
まだ読まれていない方は、よろしければ本記事に入る前に以下の内容もご覧ください。また併せて"2. 「x86環境で作成された.NET アプリケーションはppc64le環境でもそのまま動くのか」"もご覧いただけると嬉しいです。
それでは、本題に入っていきたいと思います。
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パターンが準備されていますね。
早速このコンテナイメージを使用して、.NETのサンプルコードを動かしてみましょう。
(a) サンプルコードの内容を理解する
今回ベースにしたサンプルコードは、以下のGitHubの内容です。このサンプルコードでは、.NETの実行環境用コンテナイメージに、手元の.NETのアプリケーションサンプルコードをコピーして、新たなコンテナイメージを作成しています。(Dockerfileを使用したコンテナイメージのビルド作業)
まずこのサンプルコードで実施している内容を確認していきましょう。以降の内容は、"1. 「本当に.NET 7は問題なく動くのか」"で作成したAlmaLinuxの環境で実施しています。
- 手元の環境に対象のGitHubをクローンします。
[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
[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"などが含まれています。
[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アプリケーションを起動するコンテナイメージを作成しています。
[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" の削除
[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コマンドをインストールします。
[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がインストールされました。では、コンテナイメージをビルドしてみます。
[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) 作成したコンテナイメージを実行
作成したコンテナイメージを実際に起動させてみます。
[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アーキテクチャに依存する箇所があるかどうかをチェックすることは安定稼働のためにも必要だと理解できました。
それでは、今回は以上となります。本記事が何かの参考となれば幸いです。