PaaS で動かしていた Web アプリを Cloud Run に移行する
この記事はユアマイスター アドベントカレンダー 2022の 17 日目の記事です
この記事で紹介したいこと
PaaS で動かしていた Web アプリを Docker コンテナ化し、Cloud Run にデプロイした時に行ったことを記載します。
概略
現在、筆者はブラウザゲームをプレイしています(ジャンルは育成シミュレーションです)。 そのゲームのスクリーンショットを毎日撮り、前日との数値の差分を見るようにしています。1 日あたりどれくらいゲームをプレイできているか、定期開催のイベントまでにどれくらいのペースでプレイする必要があるかなどを把握することができます。
毎日スクリーンショットから数値を手打ちするのは大変なため、画像認識ライブラリの tesseractを使った Web アプリで画像内の数値を取得し、記録するようにしています。
これまでは PaaS にデプロイして運用していましたが、この度使用していた PaaS の無料プランが削除されることになってしまいました。
有料プランに移行する、別のプラットフォームを探すなど、何かしらの対応を行う必要がありました。
いくつかの選択肢はありましたが、以下の点を踏まえ、他の PaaS ではなく Cloud Run に移行することにしました。
- 呼び出し分のみが対象となる課金体系、かつ無料枠が存在する
- コンテナさえデプロイできれば自由に設定できる実行環境
- ユアマイスターのバックエンドでは Cloud Run を使用しているので勉強になる
移行する準備
現在のファイル構成は以下の状態です。 Java のアプリケーションです。
ocr-server
├ lib
│ └ tessdata // tesseractの学習データ
└ target
└ ocr-server.jar
まずはデプロイするためのコンテナイメージを作成します。
コンテナイメージを作る
Cloud Run は、Artifact Registry にアップロードされたコンテナイメージや、GitHub のリポジトリをビルドしたものをデプロイすることができます。
今回はローカル環境で Docker コンテナのイメージを作成し、Artifact Registry にアップロードしたものをデプロイします。
まずは Docker コンテナを作ります。
Dockerfile を作成します。
FROM openjdk:20-jdk-slim-bullseye
RUN apt-get -y update
# 使用する画像認識ライブラリをインストールしておく
RUN apt-get -y install tesseract-ocr
COPY ./target/ocr-server.jar /opt/
# tesseractの学習データを配置しておく
COPY ./lib /opt/
CMD ["java", "-jar", "/opt/ocr-server.jar"]
DockerHub で OpenJDK 20 のイメージが提供されていました(2022/12/12 現在、OpenJDK 20 は Early-Access Builds)。せっかくなので新しい環境を使います。
PaaS によってはプログラムの実行環境に指定があります。そのため、場合によっては自分の使いたいものが無い可能性があります。 Cloud Run はコンテナイメージをデプロイできるため、自由に環境を選ぶことができます。
イメージをビルドし、アップロードするためにアーカイブとして保存します。
docker build . -t wusamin/ocr-server
docker save wusamin/ocr-server > ./ocr-server.tar
コンテナイメージをアップロードする
Cloud Run でコンテナイメージを利用するため、Artifact Registry にアップロードします。
Artifact Registry のリポジトリを作成します。
Google Cloud のコンソールより、 Artifact Registry のページで「リポジトリの作成」を選択します。
Docker コンテナを保存するので「形式」は Docker を選択します。リージョンは asia-northeast1 を選択します。
続いて、Docker から Artifact Registry を利用できるよう、リポジトリのホスト名を Docker Credential に追加します。
gcloud auth configure-docker asia-northeast1-docker.pkg.dev
リポジトリのホスト名は、Artifact Registry のリポジトリのページから確認できます。
コマンド実行後、"asia-northeast1-docker.pkg.dev": "gcloud"
が設定されていれば OK です。
{
"credHelpers": {
"us-central1-docker.pkg.dev": "gcloud"
}
}
Adding credentials for: asia-northeast1-docker.pkg.dev
After update, the following will be written to your Docker config file located at [/home/wusa/.docker/config.json]:
{
"credHelpers": {
"us-central1-docker.pkg.dev": "gcloud",
"asia-northeast1-docker.pkg.dev": "gcloud" <- gcloudの設定が追加されていればOK
}
}
Do you want to continue (Y/n)? Y
Docker configuration file updated.
作成した Docker イメージにタグを打ちます。
タグ名は「リージョン/プロジェクト ID/リポジトリ名/イメージ名:タグ名」の構成です。
「リージョン/プロジェクト ID/リポジトリ名」は Artifact Registry のリポジトリのページに記載のものを指定します。イメージ名は任意のものが使用可能です。タグはオプションとなっており、指定しない場合は「latest」が設定されます。
docker tag wusamin/ocr-server asia-northeast1-docker.pkg.dev/{プロジェクトID}/kanbatch/ocr-server
打ったタグを push します。
docker push asia-northeast1-docker.pkg.dev/{プロジェクトID}/kanbatch/ocr-server
Artifact Registry を確認し、push したイメージがあればアップロードは完了です。
Cloud Run にデプロイする
Artifact Registry にアップロードしたイメージからデプロイを行います。
Google Cloud のコンソールの Cloud Run の「サービスの作成」からデプロイができます。 「既存のコンテナイメージから 1 つのリビジョンをデプロイする」より、アップロードしたイメージを選択します。
デプロイするイメージを選択したら、サービスに関する設定を行います。 サービスの用途に合わせ、適当な値を設定しましょう。
「CPU の割り当てと料金」はリクエストを受信してコンテナが起動してから停止するまでの間について、リクエストを処理する時間のみか、起動から停止までの時間の全てに CPU を割り当てるかの設定です。後者はリクエストの処理後、追加で短い処理を行うことができます。今回はリクエストの処理さえできれば問題ないため「リクエストの処理中のみ CPU を割り当てる」を設定します。
「自動スケーリング」はスケールアウトの設定です。このサービスは自分しか利用しないため、ダウンタイムの発生は気にしません。最小を 0 に、最大を 1 に設定します。
「Ingress」は Cloud Run へのネットワークアクセスの制限の設定です。自宅からアクセスする、かつ Cloud Load Balancing(Google Cloud のロードバランサ)を使用しないため「すべてのトラフィックを許可する」を設定します。
「認証」はそのまま、Cloud Run へのリクエストに対して認証を付与するかどうかの設定です。Web アプリ側で認証を行っているため「未認証の呼び出しを許可」を設定します。
「作成」を押下するとデプロイが開始されます。
デプロイできたら完了です。
検証
デプロイできました。アプリの動作を検証してみましょう。
下の画像を読み取らせてみます。
読み取れました(数字の順序は Web アプリの処理の都合です)。一部スペースが混ざってはいますが、それぞれの数値を読み取ることができています。
25301 7
, 227564
, 22341 2
, 204421
, 2386
デプロイしたアプリが正常に動作していることが確認できました。
所感
PaaS に構築していた Web アプリを Cloud Run に移行させました。
PaaS の時は Java のバージョンが古いなど、実行環境に制限がある場合がありました。Cloud Run では実行環境を自分で用意できるため、柔軟な選択肢を取れるのは非常に魅力的です。
課題は認証についてです。現状では Cloud Run の呼び出しに関して認証を行っていません。アプリ側で認証自体は行っているものの、EDoS 攻撃などには弱い状態です。 Cloud Run のサービスに認証をつける他、Cloud Endpoint を使用することでも認証を行えるようなので、いずれ試して見たいと思います。
以上です。読んでいただきありがとうございました。