デベロッパー

Cloud Run と MongoDB Atlas によるサーバーレス MEAN スタック アプリケーション

※この投稿は米国時間 2022 年 6 月 14 日に、Google Cloud blog に投稿されたものの抄訳です。

願いを実現、真のサーバーレス

最先端のアプリケーション デベロッパーである Google は、パフォーマンス、柔軟性、ユーザビリティ、セキュリティ、信頼性、保守性など、多数の優先事項に対応しています。そのうえ、複数の環境や、ときには複数のリポジトリにある複数のコンポーネントの依存関係、構成、デプロイにも対処しています。さらに、安全でシンプルであることも求められています。なんとも大変なタスクです。

しかし、これが Google がサーバーレス コンピューティングを愛してやまない理由でもあります。サーバーレスであれば、デベロッパーが最も力を入れたい「開発」に集中でき、インフラストラクチャやメンテナンスといった付随的な業務をプラットフォーム サービスに任せることが可能です。

今回は、Cloud Run と MongoDB を使用した、完全にサーバーレスな MEAN スタック アプリケーションの開発エクスペリエンスを紹介します。ここでは、Cloud Run と、MongoDB のマルチクラウドのアプリケーション データ プラットフォームである MongoDB Atlas を使って、サーバーレスな MEAN アプリケーションを構築する方法を学習していきます。

Cloud Run によるコンテナ化されたデプロイメント

すべてのサーバーレス プラットフォームでは、次のような優れた機能を提供しています。

  • イベント ドリブン機能(厳格な要件ではありません)

  • インフラストラクチャのメンテナンス不要

  • 従量制料金

  • 自動スケーリング機能

そのうえで、Cloud Run には、以下のような他とは異なる機能があります。

  • リクエストを認識し、HTTP リクエストを介して起動する複数のステートレス コンテナ内で、コードをパッケージ化

  • 使用した正確なリソース量に対してのみ課金

  • 任意のプログラミング言語、オペレーティング システムのライブラリ、バイナリをサポート

こちらのリンクをクリックして、機能の全容をご確認ください。

しかしながら、従来型のデータベースが管理されていないという事実を見落としている、サーバーレス モデルも多くあります。データベースをスケーリングするために、手動でインフラストラクチャをプロビジョニングする(垂直方向のスケーリング)か、さらにサーバーを追加する(水平方向のスケーリング)必要があります。これが、サーバーレス アーキテクチャのボトルネックとなり、パフォーマンスの問題につながる可能性があります。

MongoDB Atlas でサーバーレス データベースをデプロイ

MongoDB は、この問題を解決するために、Atlas に新たにフルマネージドのサーバーレス データベースをデプロイする、サーバーレスのインスタンスをリリースしました。サーバーレスのインスタンスでは、データベースをデプロイするだけで、需要に応じてシームレスにスケールアップまたはスケールダウンできるため、インフラストラクチャについて考える必要も、手動管理も必要ありません。また、一番の利点は、実行したオペレーションに対してのみ課金されることです。アーキテクチャを真にサーバーレスにするために、Cloud Run と MongoDB Atlas の機能を組み合わせていきます。

MEAN スタックとは

MEAN スタックとは、完全に JavaScript や JSON だけでフルスタックのウェブ アプリケーションを構築するためのテクノロジー スタックのことです。MEAN スタックは、MongoDB、Express、Angular、Node.js の 4 つの主なコンポーネントで構成されています。

  • MongoDB は、データ ストレージの役割を担います。

  • Express.js は、API を構築するための、Node.js のウェブ アプリケーション フレームワークです。

  • Angular は、クライアントサイド JavaScript のプラットフォームです。

  • Node.js は、サーバーサイド JavaScript のランタイム環境です。サーバーは、MongoDB Node.js ドライバを使用してデータベースに接続し、データを取得して保存します。

Serverless MEAN Stack 1

Cloud Run と MongoDB で真にサーバーレスな MEAN スタックアプリをデプロイする手順

このセクションでは、新しい MongoDB サーバーレス インスタンスをプロビジョニングし、そこに MEAN スタック ウェブ アプリケーションを接続して、最後にアプリケーションを Cloud Run へデプロイします。

1. データベースの作成

始める前に、Google Cloud で MongoDB Atlas の使用を開始してください。
Serverless MEAN Stack 2

登録が済んだら、[Build a Database] ボタンをクリックして、新規のサーバーレス インスタンスを作成します。以下の構成を選択します。


Serverless MEAN Stack 3

サーバーレス インスタンスがプロビジョニングされたら、稼働していることを確認します。


Serverless MEAN Stack 4

[Connect] ボタンをクリックし、接続 IP アドレスとデータベースのユーザーを追加します。

このブログ投稿では、[Allow access from anywhere] の設定を使用します。MongoDB Atlas には、一連のセキュリティとアクセス機能が搭載されています。詳しくは、セキュリティ機能のドキュメントの記事をご覧ください。

データベースのユーザー名とパスワードには、任意の認証情報を使用してください。これらの手順が完了すると、次のような画面が表示されます。

Serverless MEAN Stack 5

[Choose a connection method] ボタンをクリックして次に進み、[Connect your application] を選択します。

Serverless MEAN Stack 6

表示された接続文字列をコピーし、ご自身のパスワードに置き換えます。文字列は、次のセクションでデータベースに接続する際に使用します。

2. Cloud Run プロジェクトの設定

まずは、Cloud コンソールにログインし、新しいプロジェクトを作成するか、既存のプロジェクトを使用します。

作成したプロジェクトのプロジェクト ID を覚えておいてください。以下はこちらの https://codelabs.developers.google.com/codelabs/cloud-run-hello#1、Google Cloud で新規のプロジェクトを作成する方法の説明から抜き出した画像です。

Serverless MEAN Stack 7

次に、Cloud Shell から Cloud Run API を有効にします。

1. Cloud コンソールから Cloud Shell を有効にします。[Cloud Shell をアクティブにする] をクリックするだけです。

Serverless MEAN Stack 8

2. 次のコマンドを使用します。

gcloud services enable run.googleapis.com

コードの参照用として、Cloud Shell と Cloud Shell エディタを使用します。Cloud Shell エディタにアクセスするには、Cloud Shell ターミナルから [Open Editor] をクリックします。

Serverless MEAN Stack 9

最後に、これからデプロイする MEAN スタックのプロジェクトのクローンを作成します。


デプロイするのは、従業員管理のウェブ アプリケーションです。REST API は Express と Node.js で、ウェブ インターフェースは Angular で構築されていて、データは先ほど作成した MongoDB Atlas インスタンスに保存されます。

Cloud Shell ターミナルで次のコマンドを実行して、プロジェクトのリポジトリのクローンを作成します。

git clone https://github.com/mongodb-developer/mean-stack-example.git


以降のセクションで、1 つは Express REST API 用に、もう 1 つは Angular ウェブ アプリケーション用にサービスをデプロイします。

3. Express と Node.js の REST API のデプロイ

まず、Express REST API 用に Cloud Run サービスをデプロイします。

デプロイにあたって最も重要なファイルは、Docker の構成ファイルです。詳しく見ていきましょう。

mean-stack-example/server/Dockerfile

  # Node.js 12 の公式の軽量イメージを使用します。
# https://hub.docker.com/_/node
FROM node:17-slim
 
WORKDIR /usr/app
COPY ./ /usr/app
 
# 依存関係をインストールして、プロジェクトを構築します。
RUN npm install
RUN npm run build
 
# コンテナの起動時にウェブサービスを実行します。
CMD ["node", "dist/server.js"]

この構成で Node.js が設定され、プロジェクトがコピー、構築されます。コンテナが起動すると、「node dist/server.js」のコマンドがサービスを開始します。


新しく Cloud Run のデプロイを開始するときは、左のサイドバーの Cloud Run のアイコンをクリックします。

Serverless MEAN Stack 10

それから、[Deploy to Cloud Run] のアイコンをクリックしてデプロイします。

Serverless MEAN Stack11

サービス構成は以下の内容とします。

- サービス名: node-express-api

- デプロイ プラットフォーム: Cloud Run(フルマネージド)

- リージョン: レイテンシを短縮するために、データベースのリージョンに近いリージョンを選択

- 認証: 未認証の呼び出しを許可する


「Revision Settings」で、[Show Advanced Settings] をクリックして展開します。

- コンテナポート: 5200

- 環境変数では、次の Key-Value ペアを追加します。MongoDB Atlas デプロイのための接続文字列も忘れず追加してください。

ATLAS_URI:mongodb+srv:/<username>:<password>@sandbox.pv0l7.mongodb.net/meanStackExample?retryWrites=true&w=majority

ビルド環境は、Cloud Build を選択します。

最後に、「Build Settings」のセクションでは、以下を選択します。

- ビルダー: Docker

- Docker: mean-stack-example/server/Dockerfile


[Deploy] ボタンをクリックし、次に [Show Detailed Logs] をクリックして、初めての Cloud Run サービスをデプロイします。

構築が完了すると、デプロイしたサービスの URL が表示されます。

Serverless MEAN Stack 12

URL を開き、末尾に「/employees」を追加します。今のところはまだデータベースにドキュメントがないため、空の配列が表示されます。では、ユーザー インターフェースをデプロイし、追加していきましょう。

4. Angular ウェブ アプリケーションのデプロイ

Angular アプリケーションは、クライアント ディレクトリにあります。デプロイするためには、Nginx サーバーと Docker を使用します。

> また、CDN(コンテンツ配信ネットワーク)に直接、コンテンツを提供できるので、Angular アプリケーション デプロイに Firebase Hosting を使用するという選択肢もあります。

それでは、構成ファイルを確認していきます。

mean-stack-example/client/nginx.conf

  events{}
 
http {
 
   include /etc/nginx/mime.types;
 
   server {
       listen 8080;
       server_name 0.0.0.0;
       root /usr/share/nginx/html;
       index index.html;
 
       location / {
           try_files $uri $uri/ /index.html;
       }
   }
}

Nginx の構成では、デフォルト ポート 8080 と、ファイル index.html を指定します。

mean-stack-example/client/Dockerfile

  FROM node:17-slim AS build
 
WORKDIR /usr/src/app
COPY package.json package-lock.json ./
 
# 依存関係をインストールして、コンテナにコピーします
RUN npm install
COPY . .
 
# 本番環境用に Angular アプリケーションを構築します
RUN npm run build --prod
 
# nginx ウェブサーバーを構成します
FROM nginx:1.17.1-alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=build /usr/src/app/dist/client /usr/share/nginx/html
 
# コンテナの起動時にウェブサービスを実行します。
CMD ["nginx", "-g", "daemon off;"]

Docker の構成では、Node.js の依存関係をインストールして、プロジェクトを構築します。それから、コンテナに構築したファイルをコピーし、Nginx のサービスを開始します。

最後に、クライアント アプリケーションがリクエストを送信できるように、REST API の URL を構成する必要があります。プロジェクト内の単一のファイルのみで URL を使用しているため、URL をハードコードします。別の方法としては、環境変数を window オブジェクトに加えて、そこからアクセスします。

mean-stack-example/client/src/app/employee.service.ts

   
@Injectable({
 providedIn: 'root'
})
export class EmployeeService {
 // お使いの REST API の URL に置き換えます
 private url = 'https://node-express-api-vsktparjta-uc.a.run.app'; 

Cloud Run をデプロイする準備が整いました。次の構成の設定を使用して、新しいデプロイを開始します。

- サービスの設定: サービスを作成する

- サービス名: angular-web-app

- デプロイ プラットフォーム: Cloud Run(フルマネージド)

- 認証: 未認証の呼び出しを許可する


ビルド環境は、Cloud Build を選択します。

最後に、「Build Settings」のセクションでは、以下を選択します。

- ビルダー: Docker

- Docker: mean-stack-example/client/Dockerfile


もう一度、[Deploy] ボタンをクリックし、アプリがクラウドに送られたことをログで確認します。デプロイが完了したら、クライアント アプリに URL が表示されます。


Serverless MEAN Stack 13

URL を開き、アプリケーションを操作してみましょう。

Employee Demo Thumbnail

コマンドシェルでの構築とデプロイの代替案

ここまでに説明した手順は、次のようにコマンドシェルから代わりに行うことができます。

1. コードエディタまたは Cloud Shell コマンド(ターミナル)から、「mean-stack-example」という名前で新しいプロジェクトのディレクトリを作成します。

mkdir mean-stack-demo 

cd mean-stack-demo


2. 先ほどのセクションで説明したように、プロジェクト リポジトリのクローンを作成し、構成と変数に必要な修正を加えます。


3. Cloud Shell でコマンドを実行し、Cloud Build を使用してコンテナ イメージをビルドします。

gcloud builds submit --tag gcr.io/$GOOGLE_CLOUD_PROJECT/mean-stack-demo

$GOOGLE_CLOUD_PROJECT is an environment variable containing your Google Cloud project ID when running in Cloud Shell. 


4. 以下を実行して、ローカルでテストします。

docker run -d -p 8080:8080 gcr.io/$GOOGLE_CLOUD_PROJECT/mean-stack-demo

[Web Preview]、[Preview on port 8080] をクリックします。


5. 次のコマンドを実行して、Cloud Run にコンテナ化されたアプリをデプロイします。

gcloud run deploy mean-stack-demo --image gcr.io/$GOOGLE_CLOUD_PROJECT/mean-stack-demo --platform managed --region us-central1 --allow-unauthenticated --update-env-vars DBHOST=$DB_HOST

a. –allow-unauthenticated で、認証なしでサービスを届けられるようになります。

b. –platform-managed とは、Anthos を介した Kubernetes のものではなく、フルマネージド環境をリクエストしていることを意味します。

c. –update-env-vars では、MongoDB の接続文字列は、環境変数「DBHOST」に渡されることになります。

詳細は、Secret と接続 URI 管理のための環境変数と Docker の継続的デプロイのセクションで改めて説明します。

d. デプロイが完了したら、コマンドラインにデプロイしたサービスの URL が表示されます。

e. サービスの URL に接続すると、ブラウザにウェブページと、Cloud Logging のログ エクスプローラ ページにログが表示されます。

Serverless MEAN Stack 14

5. 継続的デプロイのための環境変数と Docker

複数のコンテナ、サービス、コンポーネントにわたって構築やデプロイを行うプロセスを自動化したい場合に、リポジトリにこうした構成を保存してしまうと、扱いにくいだけではなく、セキュリティの脅威にもなってしまいます。


1. 環境間の継続的デプロイを簡単に行い、認証情報の漏洩によるセキュリティの脆弱性も回避するには、構築 / デプロイ / 稼働の時間の変数を渡すように選択します。


--update-env-vars では、実行時間だけを渡すように環境変数の値を設定できます。例の中では、変数「DBHOST」には、DB_HOST = ‘<<ENCODED CONNECTION URI>>’ と設定された $DB_HOST. の値が割り当てられます。

接続 URI のエンコードされていない記号(ユーザー名、パスワード)は、MongoDB では接続の問題となってしまう点にご注意ください。たとえば、パスワードまたはユーザー名に $ が入っている場合は、エンコードされた接続 URI では %24 に置き換えます。


2. または、ビルド時間では構成変数を環境変数として docker-compose(docker-compose.yml)に渡すこともできます。構成変数と認証情報を渡すことで、認証情報の流出を防止し、複数の環境、ユーザー、アプリケーションにわたって安全かつ継続的にデプロイを自動化できます。

まとめ

MongoDB Atlas を Cloud Run とともに使用することで、真にサーバーレスな MEAN スタック ソリューションを実現できるため、サーバーレスにアプリケーションを構築し、ステートレス コンテナで実行したい人にとっては、Cloud Run は最適な選択肢です。

最後に…

これで、Cloud Run および MongoDB Atlas 上でシンプルな MEAN スタック アプリケーションをデプロイする方法を知ることができました。ここからさらに踏み込んで、お気に入りのクライアント サーバーでのユースケースを確認してみましょう。以下のリソースを参照して、ヒントとしてお役立てください。

  1. Cloud Run HelloWorld: https://codelabs.developers.google.com/codelabs/cloud-run-hello#4

  2. MongoDB - MEAN スタック: https://www.mongodb.com/languages/mean-stack-tutorial

コメントやご質問がある場合は、オンラインで Abirami Sukumaran および Stanimira Vlaeva までお問い合わせください。


- MongoDB、デベロッパー アドボケイト Stanimira Vlaeva

Google、デベロッパー アドボケイト Abirami Sukumaran