Spring Boot WEBサービスを ACA (Azure Container Apps) で起動する (Docker Hub カスタムコンテナイメージ)
目的
Spring Boot WEBサービスを Azure Container Apps 環境で起動して理解を深めます。
実現すること
Microsoft Azure Container Apps (ACA) に Spring Boot WEBアプリのカスタムコンテナイメージをデプロイします。
この記事では、Docker Hub にプュシュしたパブリックアクセスのカスタムコンテナイメージを使用しています。 実際のシステムを構築される際にはご注意ください。
Microsoft Azure Container Registry (ACR) を使用した構成の例として、以下の記事もございます。
技術背景
Microsoft Azure Container Apps (ACA) とは?
こちらを展開してご覧いただけます。
Microsoft Azure Container Apps (ACA)
Azure 上で実行されるコンテナアプリケーションのプラットフォームです。
ACA は、Docker コンテナと Kubernetes クラスタの環境をサポートしており、開発者は Docker コンテナイメージを作成して、Kubernetes リソースとしてデプロイすることができます。また、カスタムドメイン名をサポートしているため、自社のブランドを維持することができます。
ACA の主なメリットは以下のとおりです。
簡単なセットアップとデプロイ
ACA は、簡単なユーザーインターフェイスを備えており、数回のクリックでコンテナアプリケーションをセットアップしてデプロイすることができます。
スケーラビリティ
ACA は、自動的にスケーリングを行うことができます。アプリケーションに必要なリソースが増加した場合、ACA は自動的に必要なリソースを追加して処理を分散します。
セキュリティ
ACA は、コンテナアプリケーションを実行する際に必要なセキュリティ機能を提供しています。例えば Azure Active Directory との統合や、コンテナレベルでのアクセス制御などがあります。
コスト効率
ACA は、必要なときに必要なリソースを追加するため、無駄なリソースの使用を最小限に抑えることができます。また、必要なリソースに対してのみ支払いを行うため、コスト効率的に利用することができます。
開発環境
- Windows 11 Home 22H2 を使用しています。
- WSL の Ubuntu を操作していきますので macOS の方も参考にして頂けます。
WSL (Microsoft Store アプリ版)
> wsl --version
WSL バージョン: 1.0.3.0
カーネル バージョン: 5.15.79.1
WSLg バージョン: 1.0.47
Ubuntu
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.1 LTS
Release: 22.04
Java JDK ※ Java JDK の導入と Hello World!
$ java -version
openjdk version "11.0.17" 2022-10-18
OpenJDK Runtime Environment (build 11.0.17+8-post-Ubuntu-1ubuntu222.04)
OpenJDK 64-Bit Server VM (build 11.0.17+8-post-Ubuntu-1ubuntu222.04, mixed mode, sharing)
Maven ※ Maven の導入と Hello World!
$ mvn -version
Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 11.0.17, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Docker Desktop
Version 4.16.3 (96739)
$ docker --version
Docker version 20.10.22, build 3a2c30b
$ docker-compose --version
Docker Compose version v2.15.1
※ この記事では基本的に Ubuntu のターミナルで操作を行います。
"Hello World" を表示する手順
Spring Boot WEBサービスの作成
こちらを参照して頂けます。
プロジェクトフォルダに移動
※ ~/tmp/hello-spring-boot をプロジェクトフォルダとします。
$ cd ~/tmp/hello-spring-boot
Java アプリをビルド(※参考)
※ target/app.jar が作成されます。
※ 下の コンテナイメージを作成する操作でも同時に target/app.jar が作成されるので必須ではありません。
$ mvn clean install
コンテナイメージを作成
コンテナイメージをビルド
※ ローカルの Docker 環境 (Docker Desktop) に app-hello-spring-boot コンテナイメージが作成されます。
※ コンテナイメージの作成時間が Unix エポックになるのは spring-boot:build-image の仕様です。
$ mvn spring-boot:build-image \
-Dspring-boot.build-image.imageName=app-hello-spring-boot
コンテナイメージの確認
$ docker images | grep app-hello-spring-boot
app-hello-spring-boot latest e37cc77f2b36 43 years ago 262MB
ローカルでコンテナイメージを起動して確認
$ docker run --name app-local -p 8080:8080 app-hello-spring-boot
別ターミナルから curl コマンドで確認
※ 8080 ポートでリッスン出来ているか確認します。
$ curl -v http://localhost:8080/api/data
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /api/data HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Mon, 27 Feb 2023 07:18:25 GMT
<
* Connection #0 to host localhost left intact
{"message":"Hello World!"}
Docker Hub にコンテナイメージを登録
※ $USER の部分はご自身のコンテナレジストリに読み替えて下さい。
タグ付け
$ docker tag app-hello-spring-boot $USER/app-hello-spring-boot:latest
プュシュ
$ docker push $USER/app-hello-spring-boot:latest
Docker Hub に $USER/app-hello-spring-boot:latest としてカスタムコンテナイメージが公開出来ました。
Azure のアカウントを取得
Azure CLI でサインイン
こちらを参照して頂けます。
ログイン
$ az login
※ 最新バージョンに更新する場合
$ az upgrade
Azure 環境
リソースグループ
リソースグループを作成
$ az group create \
--name rg-hello \
--location japaneast
リソースグループ一覧表示
$ az group list
※ リソースグループを削除する場合
$ az group delete -n <group>
コンテナ アプリ環境
拡張機能をインストール ※初回のみ
手順を表示します。
拡張機能
インストール
$ az extension add --name containerapp --upgrade
Microsoft.App 名前空間を登録
$ az provider register --namespace Microsoft.App
Microsoft.OperationalInsights プロバイダーを登録
$ az provider register --namespace Microsoft.OperationalInsights
コンテナ アプリ環境の作成
※ Kubernetes 基盤の環境だと思われるので少し時間がかかります。
$ az containerapp env create \
--resource-group rg-hello \
--name cae-hello \
--location japaneast
コンテナ アプリ環境の一覧表示
$ az containerapp env list
※ コンテナ アプリ環境を削除する場合
$ az containerapp env delete -n <env-name> -g <group>
コンテナ アプリ
コンテナ アプリの作成とデプロイ
※ $USER の部分はご自身のコンテナレジストリに読み替えて下さい。
$ az containerapp create \
--resource-group rg-hello \
--environment cae-hello \
--name ca-hello-spring-boot \
--image $USER/app-hello-spring-boot:latest \
--target-port 8080 \
--ingress 'external' \
--min-replicas 1
コンテナ アプリが作成されました。
Container app created. Access your app at https://ca-hello-spring-boot.agreeablepond-79ba8527.japaneast.azurecontainerapps.io/
※ コンテナ アプリを削除する場合
$ az containerapp delete -n <name> -g <group>
WEBブラウザで確認
※ URLは環境で読み替えて下さい。
https://ca-hello-spring-boot.agreeablepond-79ba8527.japaneast.azurecontainerapps.io/api/data
WEBブラウザに {"message":"Hello World!"} と表示され、JSON データを取得することが出来ました。
※ 別ターミナルから curl コマンドで確認
$ curl -v https://ca-hello-spring-boot.agreeablepond-79ba8527.japaneast.azurecontainerapps.io/api/data
* Trying 20.210.29.255:443...
* Connected to ca-hello-spring-boot.agreeablepond-79ba8527.japaneast.azurecontainerapps.io (20.210.29.255) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
* ALPN, server accepted to use h2
* Server certificate:
* subject: C=US; ST=WA; L=Redmond; O=Microsoft Corporation; CN=agreeablepond-79ba8527.japaneast.azurecontainerapps.io
* start date: Feb 25 03:06:09 2023 GMT
* expire date: Feb 20 03:06:09 2024 GMT
* subjectAltName: host "ca-hello-spring-boot.agreeablepond-79ba8527.japaneast.azurecontainerapps.io" matched cert's "*.agreeablepond-79ba8527.japaneast.azurecontainerapps.io"
* issuer: C=US; O=Microsoft Corporation; CN=Microsoft Azure TLS Issuing CA 01
* SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* Using Stream ID: 1 (easy handle 0x55c86464be80)
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET /api/data HTTP/2
> Host: ca-hello-spring-boot.agreeablepond-79ba8527.japaneast.azurecontainerapps.io
> user-agent: curl/7.81.0
> accept: */*
>
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
< HTTP/2 200
< content-type: application/json
< date: Mon, 27 Feb 2023 07:31:07 GMT
<
* Connection #0 to host ca-hello-spring-boot.agreeablepond-79ba8527.japaneast.azurecontainerapps.io left intact
{"message":"Hello World!"}
ターミナルに {"message":"Hello World!"} と表示され、JSON データを取得することが出来ました。
※ Azure 側で SSL/TLS対応と HTTP/2プロトコルを使用してくれます。
コンテナ アプリに接続
$ az containerapp exec \
--resource-group rg-hello \
--name ca-hello-spring-boot
INFO: Connecting to the container 'ca-hello-spring-boot'...
Use ctrl + D to exit.
INFO: Successfully connected to container: 'ca-hello-spring-boot'.
コンテナに接続後
$ pwd
/workspace
$ ls -la
total 20
drwxr-xr-x 1 cnb cnb 4096 Jan 1 1980 .
drwxr-xr-x 1 root root 4096 Feb 27 07:30 ..
drwxr-xr-x 1 cnb cnb 4096 Jan 1 1980 BOOT-INF
drwxr-xr-x 3 cnb cnb 4096 Jan 1 1980 META-INF
drwxr-xr-x 3 cnb cnb 4096 Jan 1 1980 org
コンテナの情報
$ cat /etc/*-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.6 LTS"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
NAME="Ubuntu"
ID=ubuntu
PRETTY_NAME="Paketo Buildpacks Base Bionic"
VERSION_ID="18.04"
HOME_URL="https://github.com/paketo-buildpacks/bionic-base-stack"
UBUNTU_CODENAME=bionic
VERSION="18.04.6 LTS (Bionic Beaver)"
ID_LIKE=debian
SUPPORT_URL="https://github.com/paketo-buildpacks/bionic-base-stack/blob/main/README.md"
BUG_REPORT_URL="https://github.com/paketo-buildpacks/bionic-base-stack/issues/new"
VERSION_CODENAME=bionic
まとめ
- Ubuntu のシンプルな構成の Java 開発環境で Spring Boot WEBサービスのカスタムコンテナイメージを ACA (Azure Container Apps) 環境で起動させることが出来ました。
個人的見解
- Azure でコンテナ化されたアプリをデプロイする環境としては一番分かりやすいと思いました。
- JVM コンテナで Hollo World するだけなら、世の中の PaaS で一番初心者向きではないでしょうか? 環境依存の特殊な設定などなく、素の JVM コンテナイメージをそのまま実行出来ました。
- 今後、他の Azure サービスでカスタムコンテナイメージを使用してアプリをデプロイする方式を比較したいと思います。
- メリット
- SSH の設定なしてデフォルトでコンテナに接続出来るのは手軽で良いと思います。
- デメリット
- 強いて上げれば初回の環境の構築に時間がかかります。
参考
[Microsoft Learn] Azure Container Apps コマンド リファレンス