IBM Cloud Code EngineにQuarkusのサンプルアプリケーションをデプロイしてみる

# はじめに
「[IBM Cloud Code Engine](https://www.ibm.com/jp-ja/cloud/code-engine)」(以下Code Engine)は、IBM Cloudで提供される新しいサーバレス環境です。

IBM Cloudでは「IBM Cloud Functions」(以下Functions)というサーバレス環境が提供されています。ただ、Functionsは軽量なREST APIの実行や、イベントに応じた簡単な処理(例えばObject Storageにファイルが格納されたら通知する、といったような処理)での利用が想定されており、既存のコンテナベースのアプリケーションを稼働させたり、バッチ処理を実行させたりといった使い方はできませんでした(Dockerコンテナを稼働させることは可能のようですが、[Docker Hubのパブリック・イメージに限定](https://cloud.ibm.com/docs/openwhisk?topic=openwhisk-prep&locale=ja#prep_docker)されます)。

Code Engineでは、Functionsで提供されていない任意のレジストリにあるコンテナベースアプリケーションの実行や、バッチジョブの実行がサポートされています。AWSで例えるならば、Lambdaに加えて、FargateやAWS Batchの機能がまとめて提供されるサービスになります。

コンテナをデプロイ・管理する環境としては Kubernetes や OpenShift が候補となりますが、環境構築に手間がかかったり、一旦構築してもその維持・管理にさらに手間がかかる、スキルが必要となるといった難しさがあります(クラウドベンダーが提供するマネージドKubernetes、OpenShiftを利用することで軽減されますが)。

Code Engineを利用することで、Kubernetesのスキルを持たなくても、Kubernetesが備えるコンテナのスケールアウトや無停止デプロイといったメリットを容易に享受できるようになります。

当記事では、マイクロサービスのJavaフレームワークである [Quarkus](https://ja.quarkus.io/) で作成したAPIサンプルアプリケーションをコンテナイメージ化したうえで、Code Engine上にデプロイする手順を紹介します。


# Quarkusのサンプルアプリケーションのコンテナイメージを作成し、IBM Cloud Container Registryに登録する

Code EngineにデプロイするAPIサンプルアプリケーションを Quarkus で準備します。このAPIは、「http(s)://<ホスト名>/hello」にアクセスすることで、「Hello RESTEasy」という文字列を返すものです。

この項の内容は当記事の本筋ではないので、コマンドと(補足説明の)コメントに留めます。

なお、以下のソフトウェアが導入済みであることを前提としています。

- JDK 8 または JDK 11以上
- Maven 3.6.2以上
- IBM Cloud CLI
- Docker Desktop for Mac、Docker Desktop for Windows

また、IBM Cloudのアカウントも必要となりますので、事前に作成しておいてください。


```
# MavenでQuarkusアプリケーションの雛形を作成する
mvn io.quarkus:quarkus-maven-plugin:1.13.3.Final:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=getting-started \
    -DclassName="org.acme.getting.started.GreetingResource" \
    -Dpath="/hello"

# 作成した雛形のディレクトリに移動
cd getting-started

# 作成したQuarkusアプリケーションを開発モードで起動
mvn compile quarkus:dev

# 起動完了後、別のターミナルでcurlを実行
# 「Hello RESTEasy」というレスポンスが得られれば成功
curl -w "\n" http://localhost:8080/hello

# 「mvn compile quarkus:dev」をCtrl+Cで止めたあと、
# QuarkusアプリケーションにDockerイメージビルド用のエクステンションを追加
mvn quarkus:add-extension -Dextensions="container-image-docker"

# アプリケーション、Dockerイメージをビルド
mvn package -Dquarkus.container-image.build=true -DskipTests=true

# 作成されたDockerイメージを確認
# デフォルトから何も変更していなければ、「<OSユーザ名>/getting-started:1.0.0-SNAPSHOT」となっているはず
docker images | grep getting-started


# IBM Cloud Container Registryにpushするために、IBM Cloudにログイン
# リージョンは東京、リソースグループはDefaultを指定
ibmcloud login -a https://cloud.ibm.com -r jp-tok -g Default

# IBM Cloud Container Registryのリージョンをap-north(東京)に設定
ibmcloud cr region-set ap-north

# Container Registryにログイン
ibmcloud cr login

# Container Registryに名前空間「quarkus-sample」を作成
# この名前空間にイメージをpushする
ibmcloud cr namespace-add quarkus-sample

# docker tagコマンドで、作成したQuarkusのDockerイメージを、Container Registryにpushできるようにタグ付け
# 「jp.icr.io/<名前空間>(先ほど作成したquarkus-sample)/<イメージ名>:<タグ>」
# 「jp.icr.io」は東京リージョンのContainer Registryのホスト名
docker tag <OSユーザ名>/getting-started:1.0.0-SNAPSHOT jp.icr.io/quarkus-sample/getting-started:latest

# Container Registryにpush
docker push jp.icr.io/quarkus-sample/getting-started:latest

# quarkus-sample名前空間にpushされていることを確認する
ibmcloud cr image-list --restrict quarkus-sample
```


# IBM Cloud Code Engineへのデプロイ

ここからが本題で、Container Registryに登録したイメージをCode Engineにデプロイしていきます。

Code Engineでは、アプリケーションは「プロジェクト」に属するかたちで管理されます。そのためまずはプロジェクトを作成していきます。

[プロジェクトの一覧ページ](https://cloud.ibm.com/codeengine/projects)にアクセスします。

「作成」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/5dbb6555-0f24-c310-cd64-0086f9c4b8b3.png)


「ロケーション」で「東京」を選択し、「名前」にプロジェクトの名前を入力(ここでは「quarkus-sample」を入力)したあと、「作成」ボタンでプロジェクトを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/fccc18a8-d01b-3f05-bc66-de1174935140.png)


「quarkus-sample」というプロジェクトが作成されているので、このプロジェクトをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/1fbd1562-2e8a-4f05-fb5d-f696202ca083.png)

Code Engineでは、HTTPリクエストを処理する「アプリケーション」と、バッチ的な処理を実行できる「ジョブ」という2タイプの処理を作成できます。ここではHTTPリクエストに応答するAPIアプリケーションをデプロイするので、「アプリケーションの作成」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/c6aa1a46-5c3f-acb0-05d0-f83a2554b791.png)


「名前」にアプリケーションの名前を入力します。
「コンテナー・イメージ」を選択し、「イメージの構成」をクリックします。
（なお、「イメージ参照」欄に、Container Registry内のイメージのパス(jp.icr.io/quarkus-sample/getting-started:latest)を直接入力することもできますが、その場合、Container Registryへのアクセス用のAPIキーが作成されず、イメージを取得できない状態になるので、「イメージの構成」からイメージを指定してください）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/458e7325-c450-1d7f-2443-98fb2aa0d8a8.png)


「レジストリー・サーバー」に「jp.icr.io」(フィールドの選択リストでは「IBM レジストリー 東京」と表示される)を選択します。
「レジストリー・アクセス」はデフォルトの「自動」とします。
その他の項目は以下の通りです。

- 名前空間　　　：　quarkus-sample
- リポジトリー　：　getting-started
- タグ　　　　　：　latest

ここまで入力したら「完了」ボタンをクリックします。
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/724eb257-c4c5-5625-4139-2444eb2135e0.png">

クリックすると元の画面に戻ります。あとの設定は変更する必要はありませんが、「ランタイム設定」の欄を展開してみます。
ここではアプリケーションのインスタンス数や、インスタンスに割り当てるリソースを設定することができます。デフォルトでは最小数が０なので、アプリケーションにアクセスが無ければインスタンスは稼働せず、課金されないことになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/b1f85efc-60af-cff9-bb1e-8744936794c6.png)

ランタイム設定を確認したら、最後に「作成」ボタンをクリックしてアプリケーションを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/de6615cd-4904-bb26-5db2-01a2072f0e90.png)

アプリケーション作成後の画面で、「準備完了」となっていることを確認し、「アプリケーションURLを開く」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/fc050731-fa63-9fb1-1556-72db733b4548.png)


以下の画面に遷移することを確認します。この画面はQuarkusが用意しているトップページです。この画面が表示された状態で、アドレスバーのURLをコピーしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/89d394a2-eec4-710d-0014-b97c463593fb.png)

curlコマンドで、QuarkusアプリケーションのAPIを実行します。

```
# <上記でコピーしたURL>の末尾に「/」がある場合、それを削除してください
curl -w "\n" <上記でコピーしたURL>/hello
```

「Hello RESTEasy」というレスポンスが得られれば、Code Engineへのデプロイは成功です。