1. はじめに
最終更新日: 2024 年 11 月 1 日
古い PHP アプリケーションを Google Cloud に移行するにはどうすればよいですか?
(📽️ この Codelab の 7 分間の紹介動画 をご覧ください)
モダナイゼーションが必要なレガシー アプリケーションがオンプレミスで実行されていることはよくあります。つまり、スケーラブルで安全な状態にし、さまざまな環境にデプロイできるようにします。
このワークショップでは、次のことを行います。
- PHP アプリケーションをコンテナ化します。
- マネージド Database Service(Cloud SQL)に移行します。
- Cloud Run にデプロイします(GKE/Kubernetes のゼロオペレーション代替)。
- Identity and Access Management(IAM)と Secret Manager を使用してアプリケーションを保護します。
- Cloud Build を使用して CI/CD パイプラインを定義します。Cloud Build は、GitHub や GitLab などの一般的な Git プロバイダでホストされている Git リポジトリに接続できます。たとえば、メインへのプッシュ時にトリガーできます。
- アプリケーションの画像を Cloud Storage でホストします。これはマウントによって実現され、アプリを変更するためのコードは必要ありません。
- Cloud Functions(サーバーレス)を介してオーケストレートされる Gemini を介して Gen AI 機能を紹介します。
- SLO と、新しく更新されたアプリの運用について理解します。
これらの手順に沿って、PHP アプリケーションを段階的にモダナイズし、スケーラビリティ、セキュリティ、デプロイの柔軟性を向上させることができます。また、Google Cloud に移行することで、強力なインフラストラクチャとサービスを活用して、クラウドネイティブ環境でアプリケーションをスムーズに実行できます。
これらの簡単な手順で学んだことは、言語やスタック、ユースケースが異なる独自のアプリケーションや組織にも適用できると考えています。
アプリについて
フォークするアプリケーション(MIT ライセンスに基づくコード)は、MySQL 認証を備えた基本的な PHP 5.7 アプリケーションです。このアプリの主な目的は、ユーザーが写真をアップロードできるプラットフォームを提供し、管理者が不適切な画像にタグ付けできるようにすることです。このアプリケーションには次の 2 つのテーブルがあります。
- ユーザー。管理者によって事前コンパイルされています。新規ユーザーを登録できる。
- 画像。サンプル画像がいくつか付属しています。ログインしたユーザーは新しい写真をアップロードできます。ここに魔法をかけます。
目標
Google Cloud で古いアプリケーションを使用できるように、モダナイズしたいと考えています。Google Cloud のツールとサービスを活用して、スケーラビリティの向上、セキュリティの強化、インフラストラクチャ管理の自動化を実現し、Cloud SQL、Cloud Run、Cloud Build、Secret Manager などのサービスを使用して、画像処理、モニタリング、データ ストレージなどの高度な機能を統合します。
さらに重要なのは、ステップごとに進めることで、各ステップの背後にある思考プロセスを学習できるようにすることです。通常、各ステップは次のステップの新しい可能性を切り開きます(例: モジュール 2 -> 3、6 -> 7)。
まだご納得いただけませんか?YouTube のこちらの 7 分間の動画をご覧ください。
必要なもの
- ブラウザがインストールされ、インターネットに接続されているパソコン。
- 一部の GCP クレジット。次のステップをご覧ください。
- Cloud Shell を使用します。必要なコマンドがすべてプリインストールされており、IDE も付属しています。
- GitHub アカウント。元のコード 🧑🏻💻 gdgpescara/app-mod-workshop を独自の git リポジトリで分岐させるために必要です。独自の CI/CD パイプライン(自動コミット -> ビルド -> デプロイ)を構築するために必要です。
サンプル ソリューションは、こちらで確認できます。
- 作成者のリポジトリ: https://github.com/Friends-of-Ricc/app-mod-workshop
- 元のワークショップ リポジトリ(
.solutions/
フォルダ内、章ごと)。
このワークショップは、Cloud Shell(ブラウザ上)で完了するように設計されています。
ただし、ローカルのパソコンから試すこともできます。
2. クレジットの設定とフォーク
GCP クレジットを利用して GCP 環境をセットアップする [省略可]
このワークショップを実施するには、クレジットが設定された請求先アカウントが必要です。独自の請求先アカウントをお持ちの場合は、この手順をスキップできます。
GCP クレジットにリンクする新しい Google Gmail アカウントを作成します(*)。GCP クレジットを利用するためのリンクを講師に尋ねるか、bit.ly/PHP-Amarcord-credits でクレジットを使用してください。
新しく作成したアカウントでログインし、手順に沿って操作します。
(
) なぜ新しい Gmail アカウントが必要なのですか?*
アカウント(特に仕事用または学生用のメールアドレス)が以前に GCP にアクセスしたことがあり、組織のポリシーによって操作が制限されているため、Codelab に合格できないというケースが確認されています。新しい Gmail アカウントを作成するか、GCP を使用したことがない既存の Gmail アカウント(gmail.com)を使用することをおすすめします。
ボタンをクリックしてクレジットを利用します。
次のフォームに名前と姓を入力し、利用規約に同意します。
請求先アカウントが https://console.cloud.google.com/billing に表示されるまで数秒かかることがあります。
完了したら、Google Cloud コンソールを開き、左上のプルダウン メニュー([組織なし] と表示されている場所)にあるプロジェクト セレクタをクリックして、新しいプロジェクトを作成します。以下をご覧ください。
下のスクリーンショットに示すように、プロジェクトがない場合は新しいプロジェクトを作成します。右上隅に [新しいプロジェクト] オプションがあります。
新しいプロジェクトを GCP トライアルの請求先アカウントにリンクしてください。
これで Google Cloud Platform を使用する準備が整いました。初心者の方や、クラウド環境ですべての操作を行いたい場合は、次の図に示すように、左上の次のボタンから Cloud Shell とそのエディタにアクセスできます。
左上で新しいプロジェクトが選択されていることを確認します。
選択されていない場合(悪い例):
選択済み(良好):
GitHub からアプリをフォークする
- デモアプリ(https://github.com/gdgpescara/app-mod-workshop)に移動します。
- 🍴 フォークをクリックします。
- GitHub アカウントをお持ちでない場合は、新しいアカウントを作成する必要があります。
- 必要に応じて編集します。
- 次のコマンドを使用してアプリコードのクローンを作成します。
git clone
https://github.com/
YOUR-GITHUB-USER/YOUR-REPO-NAME
- 任意のエディタで、クローンしたプロジェクト フォルダを開きます。Cloud Shell を選択した場合は、下の図に示すように [エディタを開く] をクリックして開きます。
次の図に示すように、Google Cloud Shell エディタに必要なものがすべて揃っています。
この操作は、[フォルダを開く] をクリックしてフォルダ(通常はホーム フォルダの app-mod-workshop
)を選択することでも実行できます。
3. モジュール 1: SQL インスタンスを作成する
Google Cloud SQL インスタンスを作成する
PHP アプリは MySQL データベースに接続するため、移行をスムーズに行うには、MySQL データベースを Google Cloud に複製する必要があります。Cloud SQL は、クラウドでフルマネージドの MySQL データベースを実行できるため、最適なソリューションです。手順は次のとおりです。
- Cloud SQL ページ(https://console.cloud.google.com/sql/instances)に移動します。
- [インスタンスを作成] をクリックします。
- API を有効にします(必要な場合)。この処理には数秒かかることがあります。
- [MySQL] を選択します。
- (最も安いバージョンを入手しようとしているため、長持ちします):
- エディション: Enterprise
- プリセット: development(Sandbox を試しましたが、うまくいきませんでした)
- Mysql Ver: 5.7(過去の遺物!)
- インスタンス ID:
appmod-phpapp
を選択します(変更する場合は、今後のスクリプトとソリューションも適宜変更してください)。 - パスワード: 任意のパスワード。ただし、CLOUDSQL_INSTANCE_PASSWORD としてメモしておきます。
- リージョン: アプリの他の部分で選択したリージョンと同じにします(例: ミラノ =
europe-west8
)。 - ゾーンの可用性: 単一ゾーン(デモ用にコストを節約)
[インスタンスを作成] ボタンをクリックして Cloud SQL データベースをデプロイします。⌛ 完了まで約 10 分かかります。⌛ その間、ドキュメントを読み進めてください。また、次のモジュール(「PHP アプリをコンテナ化する」)は、このモジュールに依存しないため、最初の部分(DB 接続を修正するまで)から開始することもできます。
注: このインスタンスの費用は 1 日あたり約 7 ドルです。ワークショップの終了後に必ずスピンオフしてください。
Cloud SQL に image_catalog DB とユーザーを作成する
アプリ プロジェクトには、2 つの SQL ファイルを含む db/
フォルダが付属しています。
- 01_schema.sql : ユーザーと画像データを含む 2 つのテーブルを作成する SQL コードが含まれています。
- 02_seed.sql: 前の手順で作成したテーブルにデータをシードする SQL コードが含まれています。
これらのファイルは、後で image_catalog
データベースが作成されたときに使用されます。手順は次のとおりです。
- インスタンスを開き、[データベース] タブをクリックします。
- [データベースを作成] をクリックします。
image_catalog
(PHP アプリの構成と同様)と呼びます。
次に、データベース ユーザーを作成します。これにより、image_catalog データベースに認証できます。
- [ユーザー] タブをクリックします。
- [ユーザー アカウントを追加] をクリックします。
- ユーザー: 作成しましょう。
- ユーザー名:
appmod-phpapp-user
- パスワード: 覚えやすいパスワードを選択するか、[生成] をクリックします。
- 「すべてのホストを許可する(%)」を保持します。
- [追加] をクリックします。
既知の IP に対して DB を開きます。
Cloud SQL のすべての DB は「分離」された状態で作成されます。アクセス可能なネットワークを明示的に設定する必要があります。
- インスタンスをクリックします。
- メニュー [Connections] を開きます。
- [ネットワーキング] タブをクリックします。
- [承認済みネットワーク] でクリックします。次に、ネットワーク(サブネットなど)を追加します。
- ここでは、アプリを動作させるために、簡単ですが安全でない設定を選択します。後で信頼できる IP に制限することをおすすめします。
- 名前: 「Everyone in the world - INSECURE」。
- ネットワーク: 「
0.0.0.0/0"
」(注: これは安全でない部分です) - [完了] をクリックします。
- [保存] をクリックします。
次のように表示されます。
注: このソリューションは、ワークショップを O(時間) で完了するための妥協案として適しています。ただし、セキュリティ ドキュメントを確認して、本番環境用のソリューションを保護してください。
DB 接続をテストしましょう。
以前に作成した image_catalog
ユーザーが機能するかどうかを確認してみましょう。
インスタンス内の [Cloud SQL Studio] にアクセスし、次の図に示すように、認証するデータベース、ユーザー、パスワードを入力します。
これで SQL エディタを開いて、次のセクションに進むことができます。
コードベースからデータベースをインポートする
SQL エディタを使用して、image_catalog
テーブルとそのデータをインポートします。リポジトリのファイル(01_schema.sql、02_seed.sql)から SQL コードをコピーし、順番に実行します。
この後、image_catalog に users と images の 2 つのテーブルが作成されます。
エディタで select * from images;
を実行してテストできます。
Cloud SQL インスタンスのパブリック IP アドレスもメモしておいてください。後で必要になります。IP を取得するには、[概要] ページの Cloud SQL インスタンスのメインページに移動します。([概要] > [このインスタンスに接続] > [パブリック IP アドレス])。
4. モジュール 2: PHP アプリをコンテナ化する
このアプリをクラウド向けに構築します。
つまり、コードを Cloud で実行するためのすべての情報を含む ZIP ファイルにパッケージ化します。
パッケージ化する方法はいくつかあります。
- Docker。非常に人気がありますが、正しく設定するにはかなり複雑です。
- Buildpacks。あまり一般的ではありませんが、ビルドする内容と実行する内容を自動的に推測する傾向があります。多くの場合、問題なく動作します。
このワークショップでは、Docker を使用することを前提としています。
Cloud Shell を使用することを選択した場合は、ここで Cloud Shell を再度開きます(Cloud コンソールの右上をクリックします)。
ページの最下部に便利なシェルが開きます。このシェルで、セットアップ手順でコードをフォークする必要があります。
Docker
制御が必要な場合は、このソリューションが適しています。これは、特定のライブラリを構成し、特定のわかりにくい動作(アップロード時の chmod、アプリ内の非標準の実行可能ファイルなど)を挿入する必要がある場合に意味があります。
最終的にコンテナ化されたアプリケーションを Cloud Run にデプロイするため、次のドキュメントを確認してください。php 8 から PHP 5.7 にバックポートするにはどうすればよいですか?Gemini を使用して、または、次の事前作成バージョンを使用することもできます。
# Use the official PHP image: https://hub.docker.com/_/php
FROM php:5.6-apache
# Configure PHP for Cloud Run.
# Precompile PHP code with opcache.
# Install PHP's extension for MySQL
RUN docker-php-ext-install -j "$(nproc)" opcache mysqli pdo pdo_mysql && docker-php-ext-enable pdo_mysql
RUN set -ex; \
{ \
echo "; Cloud Run enforces memory & timeouts"; \
echo "memory_limit = -1"; \
echo "max_execution_time = 0"; \
echo "; File upload at Cloud Run network limit"; \
echo "upload_max_filesize = 32M"; \
echo "post_max_size = 32M"; \
echo "; Configure Opcache for Containers"; \
echo "opcache.enable = On"; \
echo "opcache.validate_timestamps = Off"; \
echo "; Configure Opcache Memory (Application-specific)"; \
echo "opcache.memory_consumption = 32"; \
} > "$PHP_INI_DIR/conf.d/cloud-run.ini"
# Copy in custom code from the host machine.
WORKDIR /var/www/html
COPY . .
# Setup the PORT environment variable in Apache configuration files: https://cloud.google.com/run/docs/reference/container-contract#port
ENV PORT=8080
# Tell Apache to use 8080 instead of 80.
RUN sed -i 's/80/${PORT}/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf
# Note: This is quite insecure and opens security breaches. See last chapter for hardening ideas.
# Uncomment at your own risk:
#RUN chmod 777 /var/www/html/uploads/
# Configure PHP for development.
# Switch to the production php.ini for production operations.
# RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
# https://github.com/docker-library/docs/blob/master/php/README.md#configuration
RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
# Expose the port
EXPOSE 8080
最新の Dockerfile
バージョンはこちらで入手できます。
アプリケーションをローカルでテストするには、PHP アプリが Google CloudSQL で使用可能な MYSQL データベースに接続するように config.php ファイルを変更する必要があります。以前に設定した内容に基づいて、空欄に入力します。
<?php
// Database configuration
$db_host = '____________';
$db_name = '____________';
$db_user = '____________';
$db_pass = '____________';
try {
$pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Errore di connessione: " . $e->getMessage());
}
session_start();
?>
DB_HOST
は Cloud SQL のパブリック IP アドレスです。SQL コンソールで確認できます。
DB_NAME
は変更しない:image_catalog
DB_USER
はappmod-phpapp-user
にしますDB_PASS
は、お客様が選択したものです。単一引用符で囲み、必要に応じてエスケープします。
また、Gemini を使用して、イタリア語のいくつかの部分を英語に翻訳することもできます。
Dockerfile
を取得し、DB に接続するように PHP アプリを構成したので、試してみましょう。
まだインストールしていない場合は、docker をインストールします(リンク)。Cloud Shell を使用している場合は、この操作は必要ありません。
適切な docker ビルド コマンドと実行コマンドを使用して、コンテナ化された PHP アプリをビルドして実行してみます。
# Build command - don't forget the final . This works if Dockerfile is inside the code folder:
$ docker build -t my-php-app-docker .
# Local Run command: most likely ports will be 8080:8080
$ docker run -it -p <CONTAINER_PORT>:<LOCAL_MACHINE_PORT> my-php-app-docker
すべてが正常に機能している場合は、ローカルホストに接続すると次のウェブページが表示されます。アプリがポート 8080 で実行されているので、[ウェブでプレビュー] アイコン(目のアイコンが付いたブラウザ)をクリックし、[ポート 8080 でプレビュー](または、他のポートの場合は [ポートの変更])をクリックします。
ブラウザで結果をテストする
アプリケーションは次のようになります。
Admin/admin123 でログインすると、次のように表示されます。
素晴らしいです。イタリア語のテキスト以外は機能しています。🎉🎉🎉
docker 化は適切に行われているが、DB の認証情報が間違っている場合は、次のようなエラーが表示されることがあります。
もう一度お試しください。正解まであと少しです。
Artifact Registry への保存 [省略可]
これで、クラウドにデプロイする準備が整ったコンテナ化された PHP アプリケーションが完成しました。次に、Docker イメージを保存し、Cloud Run などの Google Cloud サービスにデプロイできるようにするクラウド内の場所が必要です。このストレージ ソリューションは Artifact Registry と呼ばれます。これは、Docker コンテナ イメージ、Maven パッケージ、npm モジュールなどのアプリケーション アーティファクトを保存するために設計されたフルマネージドの Google Cloud サービスです。
適切なボタンを使用して、Google Cloud Artifact Registry にリポジトリを作成しましょう。
有効な名前、形式、アーティファクトの保存に適したリージョンを選択します。
ローカル開発環境に戻り、App コンテナ イメージにタグを付けて、作成した Artifact Registry リポジトリに push します。次のコマンドを実行します。
- docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
- docker push TARGET_IMAGE[:TAG]
結果は次のスクリーンショットのようになります。
おめでとうございます 🎉🎉🎉 次のレベルに進むことができます。それまでの間に、アップロード、ログイン、ログアウトを 2 分ほど試して、アプリのエンドポイントに慣れておきましょう。後で必要になります。
発生する可能性があるエラー
コンテナ化エラーが発生した場合は、Gemini を使用してエラーの説明と修正を試してください。次の情報を提供します。
- 現在の Dockerfile
- 発生したエラー
- [必要に応じて] 実行中の PHP コード。
アップロード権限。また、/upload.php
エンドポイントを試して、写真をアップロードしてみてください。次のエラーが表示されることがあります。その場合は、Dockerfile
で chmod/chown
の修正を行う必要があります。
警告: move_uploaded_file(uploads/image (3).png): failed to open stream: Permission denied in /var/www/html/upload.php on line 11
PDOException "could not find driver"(または「Errore di connessione: could not find driver」)。DB に接続するために、Dockerfile に mysql(pdo_mysql
)用の適切な PDO ライブラリがあることを確認します。こちらでソリューションのヒントをご覧ください。
リクエストをバックエンドに転送できません。ポート 8080 のサーバーに接続できませんでした。これは、間違ったポートを公開している可能性が高いことを意味します。Apache/Nginx が実際に提供しているポートを公開していることを確認します。これは些細なことではありません。可能であれば、ポートを 8080 に設定してください(Cloud Run での作業が簡単になります)。ポート 80 を維持する場合は(Apache がそのように要求している場合など)、別のコマンドを使用して実行します。
$ docker run -it -p 8080:80 # force 80
# Use the PORT environment variable in Apache configuration files.
# https://cloud.google.com/run/docs/reference/container-contract#port
RUN sed -i 's/80/${PORT}/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf
5. モジュール 3: Cloud Run にアプリをデプロイする
Cloud Run を選ぶ理由
ごもっともなご質問です。数年前であれば、間違いなく Google App Engine を選択していたでしょう。
簡単に言うと、現在の Cloud Run は新しい技術スタックを備えており、デプロイが簡単で、費用も安く、使用しないときは 0 までスケールダウンします。ステートレス コンテナを実行できる柔軟性と、さまざまな Google Cloud サービスとの統合により、最小限のオーバーヘッドと最大限の効率でマイクロサービスと最新のアプリケーションをデプロイするのに最適です。
具体的には、Cloud Run は、サーバーレス環境でステートレス コンテナ化アプリケーションを実行できるようにする、Google Cloud のフルマネージド プラットフォームです。すべてのインフラストラクチャを自動的に処理し、トラフィックの増加に合わせてゼロからスケールアップし、アイドル状態になるとスケールダウンするため、費用対効果が高く、効率的です。Cloud Run は、コンテナにパッケージ化されていれば、あらゆる言語やライブラリをサポートしているため、開発の柔軟性が大幅に向上します。他の Google Cloud サービスとの統合もスムーズです。サーバー インフラストラクチャを管理することなく、マイクロサービス、API、ウェブサイト、イベント ドリブン アプリケーションを構築するのに適しています。
前提条件
このタスクを完了するには、ローカルマシンに gcloud
がインストールされている必要があります。表示されない場合は、こちらの手順をご覧ください。Google Cloud Shell を使用している場合は、何もする必要はありません。
デプロイする前に...
ローカル環境で作業している場合は、次のコマンドを使用して Google Cloud に対する認証を行います。
$ gcloud auth login –update-adc # not needed in Cloud Shell
これにより、ブラウザで OAuth ログインによる認証が行われます。課金が有効になっている Google Cloud にログインしているユーザー(vattelapesca@gmail.com など)と同じユーザーで Chrome からログインしていることを確認します。
次のコマンドで Cloud Run API を有効にします。
$ gcloud services enable run.googleapis.com cloudbuild.googleapis.com
これで、Cloud Run にデプロイする準備が整いました。
gcloud を使用してアプリを Cloud Run にデプロイする
Cloud Run にアプリをデプロイできるコマンドは gcloud run deploy
です。目標を達成するために設定できるオプションはいくつかあります。最小限のオプション(コマンドラインで指定するか、ツールがインタラクティブ プロンプトで尋ねます)は次のとおりです。
- アプリにデプロイする Cloud Run サービスの名前。Cloud Run サービスは、アプリのエンドポイントを提供する URL を返します。
- アプリが実行される Google Cloud リージョン。(
--region
REGION) - アプリをラップするコンテナ イメージ。
- アプリの実行時に使用する必要がある環境変数。
- Allow-Unauthenticated フラグ: 追加の認証なしで誰でもアプリにアクセスできるようにします。
このオプションをコマンドラインに適用する方法については、ドキュメントをご覧ください(または、下にスクロールして解決策をご覧ください)。
デプロイには数分かかります。すべてが正しければ、Google Cloud コンソールに次のようなものが表示されます。
Cloud Run から提供された URL をクリックして、アプリケーションをテストします。認証が完了すると、次のような画面が表示されます。
引数なしの「gcloud run deploy」
gcloud run deploy
は、適切な質問をして、ユーザーが残した空白を埋めることに気づかれたかもしれません。この盛り上がり!
ただし、いくつかのモジュールでこのコマンドを Cloud Build トリガーに追加するため、インタラクティブな質問はできません。コマンドのすべてのオプションを入力する必要があります。そこで、黄金の gcloud run deploy --option1 blah --foo bar --region your-fav-region
を作成します。どうすればよいですか。
- gcloud が質問を停止するまで、手順 2 ~ 3 ~ 4 を繰り返します。
- [ループ]
gcloud run deploy
(これまでに検出されたオプションを含む) - [LOOP] システムがオプション X を要求する
- [ループ]
--my-option [my-value]
オプションを追加して CLI から X を設定する方法について、公開ドキュメントを検索します。 - gcloud が追加の質問なしで完了しない限り、ステップ 2 に戻ります。
- この gcloud run deploy BLAH BLAH BLAH は最高です。コマンドをどこかに保存します。これは後で Cloud Build ステップで必要になります。
解決策については、こちらをご覧ください。ドキュメントはこちらをご覧ください。
おめでとうございます 🎉🎉🎉 Google Cloud にアプリをデプロイし、モダナイゼーションの最初のステップを完了しました。
6. モジュール 4: Secret Manager でパスワードをクリーンアップする
前のステップでは、Cloud Run でアプリを正常にデプロイして実行できました。ただし、セキュリティの悪いプラクティス(一部のシークレットをクリアテキストで提供する)を使用していました。
最初のイテレーション: ENV を使用するように config.php を更新する
config.php ファイルのコードに DB パスワードを直接記述していることに気づかれたかもしれません。これは、テスト目的やアプリが動作するかどうかを確認する目的には適しています。ただし、本番環境でそのようなコードを commit したり使用したりすることはできません。パスワード(およびその他の DB 接続パラメータ)は動的に読み取られ、実行時にアプリに提供される必要があります。config.php ファイルを変更して、ENV 変数から db パラメータを読み取るようにします。失敗した場合は、デフォルト値の設定を検討してください。これは、ENV の読み込みに失敗した場合に、ページ出力でデフォルト値が使用されているかどうかを確認できるため便利です。空欄を埋めて、config.php のコードを置き換えます。
<?php
// Database configuration with ENV variables. Set default values as well
$db_host = getenv('DB_HOST') ?: 'localhost';
$db_name = getenv('DB_NAME') ?: 'image_catalog';
$db_user = getenv('DB_USER') ?: 'appmod-phpapp-user';
$db_pass = getenv('DB_PASS') ?: 'wrong_password';
// Note getenv() is PHP 5.3 compatible
try {
$pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Errore di connessione: " . $e->getMessage());
}
session_start();
?>
アプリがコンテナ化されているため、アプリに ENV 変数を渡す方法を提供する必要があります。これにはいくつかの方法があります。
- Dockerfile のビルド時。構文 ENV DB_VAR=ENV_VAR_VALUE を使用して、前の Dockerfile に 4 つのパラメータを追加します。これにより、実行時にオーバーライドできるデフォルト値が設定されます。たとえば、ここで「DB_NAME」と「DB_USER」を設定すると、他の場所では設定できなくなります。
- 実行時。これらの変数は、CLI または UI の両方から Cloud Run に設定できます。Dockerfile で設定されたデフォルトを維持する場合を除き、4 つの変数をすべてここに配置します。
ローカルホストでは、ENV 変数を .env
ファイルに配置することをおすすめします(solutions フォルダを確認してください)。
また、.env が .gitignore
に追加されていることを確認してください。シークレットを GitHub に push しないようにする必要があります。
echo .env >> .gitignore
その後、インスタンスをローカルでテストできます。
docker run -it -p 8080:8080 --env-file .env my-php-app-docker
これで、次のことが実現しました。
- アプリは ENV から変数を動的に読み取ります
- (コードから DB パスワードを削除したため、セキュリティが強化されました)。
これで、Cloud Run に新しいリビジョンをデプロイできるようになりました。UI に移動して、環境変数を手動で設定しましょう。
- https://console.cloud.google.com/run に移動します。
- アプリをクリックします。
- [新しいリビジョンの編集とデプロイ] をクリックします。
- 最初のタブ [コンテナ] で、下のタブ [変数とシークレット] をクリックします。
- [+ 変数を追加] をクリックして、必要な変数をすべて追加します。最終的に次のようになります。
これで完璧ですか?いいえ。ほとんどの事業者に PASS が表示されます。これは、Google Cloud Secret Manager で軽減できます。
2 回目のイテレーション: Secret Manager
パスワードがコードから消えました。これで完了です。しかし、まだ安全とは言えません。
パスワードは、Google Cloud コンソールにアクセスできるすべてのユーザーに引き続き表示されます。実際、Cloud Run YAML デプロイ ファイルにアクセスすると、取得できます。また、新しい Cloud Run リビジョンを編集またはデプロイしようとすると、次のスクリーンショットに示すように、[変数とシークレット] セクションにパスワードが表示されます。
Google Cloud の Secret Manager は、API キー、パスワード、証明書などの機密情報を管理するための安全な一元管理サービスです。
これにより、きめ細かい権限と堅牢な暗号化を使用して、シークレットを保存、管理、アクセスできます。Google Cloud の Identity and Access Management(IAM)と統合された Secret Manager を使用すると、特定のシークレットにアクセスできるユーザーを制御し、データ セキュリティと規制遵守を確保できます。
また、シークレットの自動ローテーションとバージョン管理もサポートしているため、シークレットのライフサイクル管理が簡素化され、Google Cloud サービス全体でアプリケーションのセキュリティが強化されます。
Secret Manager にアクセスするには、ハンバーガー メニューから [セキュリティ] サービスに移動し、下のスクリーンショットに示すように、[データ保護] セクションで確認します。
次の図に示すように、Secret Manager API を有効にします。
- [シークレットを作成] をクリックします。ここでは、シークレットに「rationally」という名前を付けます。
- 名前:
php-amarcord-db-pass
- シークレット値: 「your DB password」(「upload file」の部分は無視します)。
- このシークレット リンクにアノテーションを付けます。
projects/123456789012/secrets/php-amarcord-db-pass
のようになります。これは、シークレットへの一意のポインタです(Terraform、Cloud Run など)。この番号は、固有のプロジェクト番号です。
ヒント: シークレットに一貫した命名規則を使用し、左から右に特化するようにしてください(例: cloud-devrel-phpamarcord-dbpass
)。
- 組織(会社)
- チーム(組織内)
- アプリケーション(チーム内)
- 変数名(アプリ内)
これにより、1 つのアプリのすべてのシークレットを簡単に見つけることができる正規表現を作成できます。
新しい Cloud Run リビジョンを作成する
新しい Secret が作成されたので、DB_PASS 環境変数を削除し、新しい Secret に置き換える必要があります。それによって次のようになります。
- Google Cloud コンソールを使用した Cloud Run へのアクセス
- アプリを選択します。
- [新しいリビジョンの編集とデプロイ] をクリックします。
- [変数とシークレット] タブを見つけます。
- [+ Reference a Secret] ボタンを使用して、DB_PASS ENV 変数をリセットします。
- 参照される Secret に同じ「DB_PASS」を使用し、最新バージョンを使用します。
完了すると、次のエラーが表示されます。
修正方法を検討してください。この問題を解決するには、[IAM と管理] セクションにアクセスして、権限の付与を変更する必要があります。デバッグをお楽しみください。
原因が特定できたら、Cloud Run に戻って新しいリビジョンを再デプロイします。結果は次の図のようになります。
ヒント: デベロッパー コンソール(UI)は、権限の問題を指摘するのに優れています。Cloud エンティティのすべてのリンクをたどってみましょう。
7. モジュール 5: Cloud Build で CI/CD を設定する
CI/CD パイプラインが必要な理由
ここまでで、gcloud run deploy
を数回入力したはずです。同じ質問に何度も答えたかもしれません。
gcloud run deploy を使用してアプリを手動でデプロイするのは面倒ですか?新しい変更を Git リポジトリに push するたびに、アプリが自動的にデプロイされたら便利だと思いませんか?
CI/CD パイプラインを使用するには、次の 2 つが必要です。
- 個人の Git リポジトリ: 幸いなことに、ステップ 2 でワークショップ リポジトリを GitHub アカウントにフォークしているはずです。完了していない場合は、前の手順に戻って完了してください。フォークしたリポジトリは次のようになります。
https://github.com/<YOUR_GITHUB_USER>/app-mod-workshop
- Cloud Build。この優れた安価なサービスを使用すると、Terraform や Docker 化されたアプリなど、ほぼすべてのビルド自動化を構成できます。
このセクションでは、Cloud Build の設定に焦点を当てます。
Cloud Build のご紹介
Cloud Build を使用して、次の操作を行います。
- ソースをビルドします(Dockerfile を使用)。これは、ビルドと実行に必要なすべてのもの(「ビルド アーティファクト」)を含む「大きな .zip ファイル」と考えることができます。
- このアーティファクトを Artifact Registry(AR)に push します。
- 次に、AR から Cloud Run にアプリ「php-amarcord」のデプロイを発行します。
- これにより、既存のアプリの新しいバージョン(新しいコードを含むレイヤ)が作成されます。プッシュが成功した場合にトラフィックを新しいバージョンに転送するように構成します。
以下は、php-amarcord
アプリのビルドの例です。
これらをどのように実現しているのでしょうか?
- 完璧な YAML ファイル
cloudbuild.yaml
を作成します。 - Cloud Build トリガーを作成します。
- Cloud Build UI を介して GitHub リポジトリに接続します。
トリガーを作成する(リポジトリを接続する)
- https://console.cloud.google.com/cloud-build/triggers に移動します。
- [トリガーを作成] をクリックします。
- コンパイル:
- 名前:
on-git-commit-build-php-app
のようなわかりやすい名前 - イベント: ブランチに push する
- ソース: 「新しいリポジトリに接続」
- 右側に [リポジトリを接続] ウィンドウが開きます。
- ソース プロバイダ: 「Github」(最初)
- 「続行」
- Authenticate を実行すると、GitHub で相互認証を行うためのウィンドウが開きます。フローに沿って、辛抱強く対応してください。リポジトリが多い場合は、時間がかかることがあります。
- [Select repo] で、アカウント/リポジトリを選択し、[I understand...] の部分にチェックを入れます。
- 「GitHub アプリは、どのリポジトリにもインストールされていません」というエラーが表示された場合は、[Google Cloud Build をインストール] をクリックして、手順に沿って操作します。
[接続] をクリックします。
- ビンゴ!これでリポジトリが接続されます。
- トリガー部分に戻ります。
- 構成: 自動検出(*)
- 詳細: サービス アカウント「[PROJECT_NUMBER]- compute@developer.gserviceaccount.com」を選択します。
- xxxxx はプロジェクト ID です
- デフォルトのコンピューティング サービス アカウントはラボ アプローチに適していますが、本番環境では使用しないでください。(詳細)。
- 他の設定はそのままにします。
- [作成] ボタンをクリックします。
(*)Dockerfile または cloudbuild.yaml をチェックするため、これが最も簡単な方法です。ただし、cloudbuild.yaml
を使用すると、どのステップで何を行うかを実際に決定できます。
I've got the power!
これで、Cloud Build サービス アカウント(サービス アカウントとは)に権限を付与しない限り、トリガーは機能しません。タスク(この場合は Cloud でのビルド)をユーザーに代わって実行する「ロボット」のメールアドレス。
SA に権限を付与しないと、SA はビルドとデプロイに失敗します。幸いにも、手順は簡単です。
- [Cloud Build] > [設定] に移動します。
- 「[PROJECT_NUMBER]- compute@developer.gserviceaccount.com」サービス アカウント
- 次のチェックボックスをオンにします。
- Cloud Run
- Secret Manager
- サービス アカウント
- Cloud Build
- [優先サービス アカウントとして設定] もオンにします。
Cloud Build YAML はどこにありますか?
独自の Cloud Build YAML を作成することをおすすめします。
ただし、時間がない場合や、時間をかけたくない場合は、このソリューション フォルダ(.solutions)でヒントを得ることができます。
これで、github に変更を push して、Cloud Build の動作を確認できます。
Cloud Build の設定は難しい場合があります。次のようなやり取りが予想されます。
- https://console.cloud.google.com/cloud-build/builds;region=global でログを確認する
- エラーの確認。
- コードを修正し、git commit / git push を再発行します。
- エラーがコードではなく、構成にある場合もあります。その場合は、UI から新しいビルドを発行できます([Cloud Build] > [トリガー] > [実行])。
この解決策を使用する場合でも、まだ作業が必要になります。たとえば、新しく作成した開発/本番環境のエンドポイントの ENV 変数を設定する必要があります。
作成する方法は次の 2 つです。
- UI 経由 - 環境変数を再度設定する
- CLI を使用して、ユーザーに最適なスクリプトを作成します。例については、gcloud-run-deploy.sh をご覧ください。エンドポイントやプロジェクト番号など、いくつかの調整が必要です。プロジェクト番号は Cloud の概要で確認できます。
GitHub にコードをコミットするにはどうすればよいですか?
このワークショップでは、github に git push
する最適な方法については説明しません。ただし、行き詰まって Cloud Shell を使用している場合は、次の 2 つの方法があります。
- CLI。ローカルで SSH 認証鍵を追加し、git@github.com:YOUR_USER/app-mod-workshop.git(http ではなく)でリモートを追加します。
- VSCode。Cloud Shell エディタを使用している場合は、[ソース管理](Ctrl+Shift+G)タブを使用し、[変更を同期] をクリックして、手順に沿って操作します。github アカウントを vscode に認証すると、そこからの pull/push が簡単になります。
git add clodubuild.yaml
を他のファイルと一緒に保存してください。そうしないと、機能しません。
「開発/本番環境のパリティ」の深さと浅さ [省略可]
こちらからモデル バージョンをコピーした場合、同じ DEV バージョンと PROD バージョンが 2 つ存在することになります。これは Twelve-Factor App のルール 10 に沿った優れた方法です。
ただし、アプリが同じデータベースを指すように、2 つの異なるウェブ エンドポイントを使用しています。ワークショップではこれで十分ですが、実際には、適切な本番環境を作成するために時間をかける必要があります。つまり、2 つのデータベース(開発用と本番環境用)を用意し、障害復旧 / 高可用性のためにどこに配置するかを選択します。これはこのワークショップの範囲を超えていますが、考えるきっかけになれば幸いです。
本番環境の「詳細」バージョンを作成する時間がある場合は、次のような複製する必要があるすべてのリソースを考慮してください。
- Cloud SQL データベース(および SQL インスタンス)。
- GCS バケット
- Cloud Functions。
- 開発環境では Gemini 1.5 Flash をモデルとして使用し(より安価で高速)、Gemini 1.5 Pro を使用する(より強力)。
一般に、アプリについて何かを行うたびに、本番環境で同じ値を使用すべきかどうかを批判的に検討します。そうでない場合は、重複した作業が発生します。もちろん、Terraform では、環境(-dev、-prod)をリソースの接尾辞として挿入できるため、この作業ははるかに簡単です。
8. モジュール 6: Google Cloud Storage への移行
ストレージ
現在、アプリは状態を Docker コンテナに保存しています。マシンが故障した場合、アプリがクラッシュした場合、または単に新しいリビジョンを push した場合、新しいリビジョンがスケジュールされ、新しい空のストレージが作成されます。🙈
この問題を解決するには、いくつかの方法があります。
- 画像を DB に保存します。以前の PHP アプリでは、最終的にこの方法を採用しました。複雑さを増すことなく、最もシンプルなソリューションです。ただし、DB にレイテンシと負荷が追加されることは確かです。
- Cloud Run アプリをストレージ フレンドリーなソリューション(GCE + 永続ディスク)に移行しますか?GKE + Storage などが考えられます。注: 制御性が高まるほど、俊敏性は低下します。
- GCS に移動します。Google Cloud Storage は、Google Cloud 全体で最高水準のストレージを提供し、最もクラウドらしいソリューションです。ただし、PHP ライブラリを扱う必要があります。GCS 用の PHP 5.7 ライブラリはありますか?
PHP 5.7
はComposer
をサポートしていますか(Composer でサポートされている最も古いバージョンは PHP 5.3.2 のようです)。 - Docker サイドカーを使用することもできます。
- または、GCS の Cloud Run ボリューム マウントを使用します。素晴らしいですね。
🤔 ストレージを移行する(オープン エンド)
[オープンエンド] この演習では、画像を何らかの方法で永続化された状態で移動させるソリューションを見つけてください。
受け入れテスト
解決策は教えたくないのですが、次のことを実現したいです。
newpic.jpg
をアップロードします。アプリで確認できます。- アプリを新しいバージョンにアップグレードします。
newpic.jpg
は引き続き表示されます。
💡 解決策(GCS Cloud Run ボリューム マウント)
これは非常にエレガントなソリューションであり、コードに一切触れることなく(画像の説明を表示する以外は)、ステートフルなファイル アップロードを実現できます(画像の説明は些細なことであり、単に見た目を良くするためだけのものです)。
これにより、Cloud Run から GCS にフォルダをマウントできるようになります。
- GCS へのアップロードはすべてアプリに表示されます。
- アプリへのアップロードはすべて GCS にアップロードされます
- GCS にアップロードされたオブジェクトにマジックが適用されます(第 7 章)。
注: FUSE の注意事項をお読みください。パフォーマンスが問題になる場合は、これは適切ではありません。
GCS バケットを作成する
GCS は、Google Cloud のどこにでも存在するストレージ サービスです。これは実戦でテストされており、ストレージを必要とするすべての GCP サービスで使用されています。
Cloud Shell は PROJECT_ID を GOOGLE_CLOUD_PROJECT としてエクスポートします。
$ export PROJECT_ID=$GOOGLE_CLOUD_PROJECT
#!/bin/bash
set -euo pipefail
# Your Cloud Run Service Name, eg php-amarcord-dev
SERVICE_NAME='php-amarcord-dev'
BUCKET="${PROJECT_ID}-public-images"
GS_BUCKET="gs://${BUCKET}"
# Create bucket
gsutil mb -l "$GCP_REGION" -p "$PROJECT_ID" "$GS_BUCKET/"
# Copy original pictures there - better if you add an image of YOURS before.
gsutil cp ./uploads/*.png "$GS_BUCKET/"
/uploads/ フォルダにバケットをマウントするように Cloud Run を構成する
ここからがエレガントな部分です。ボリューム php_uploads
を作成し、Cloud Run に MOUNT_PATH
で FUSE マウントを行うよう指示します(/var/www/html/uploads/
など)。
#!/bin/bash
set -euo pipefail
# .. keep variables from previous script..
# Uploads folder within your docker container.
# Tweak it for your app code.
MOUNT_PATH='/var/www/html/uploads/'
# Inject a volume mount to your GCS bucket in the right folder.
gcloud --project "$PROJECT_ID" beta run services update "$SERVICE_NAME" \
--region $GCP_REGION \
--execution-environment gen2 \
--add-volume=name=php_uploads,type=cloud-storage,bucket="$BUCKET" \
--add-volume-mount=volume=php_uploads,mount-path="$MOUNT_PATH"
Cloud Storage を指すようにするすべてのエンドポイントについて、この手順を繰り返します。
UI から同じ操作を行うこともできます。
- [ボリューム] タブで、バケットを指すボリューム マウントを作成します。タイプは [Cloud Storage バケット] で、名前は php_uploads などにします。
- [Container(s)] > [Volume Mounts] で、作成したボリュームをアプリでリクエストされたボリューム ポイントにマウントします。これは Dockerfile によって異なりますが、
var/www/html/uploads/
のようになります。
いずれの場合も、新しい Cloud Run リビジョンを編集すると、次のような内容が表示されます。
次に、新しいアプリケーションをテストします。新しい画像を /upload.php
エンドポイントにアップロードします。
PHP を 1 行も書かずに、GCS で画像をシームレスにフローさせる必要があります。
何が起こったのか。
魔法のようなことが起こりました。
古いコードを含む古いアプリケーションがまだ動作しています。新しい最新のスタックにより、アプリ内のすべての画像/写真をステートフルな Cloud バケットに快適に配置できます。可能性は無限大です。
- 「危険」または「ヌード」の画像が届くたびにメールを送信したいですか?これは PHP コードを変更することなく行えます。
- 画像が入力されるたびに Gemini マルチモーダル モデルを使用して画像を説明し、その説明とともに DB をアップロードしたいですか?PHP コードを変更することなく、これを行うことができます。信じていただけないようですね。第 7 章で詳しく説明します。
ここで大きなチャンスが広がりました。
9. モジュール 7: Google Gemini を活用してアプリを強化する
これで、Cloud 化されたストレージを備えた、最新の素晴らしい PHP アプリ(2024 年の Fiat 126
など)が完成しました。
用途
前提条件
前の章のモデル ソリューションでは、GCS に画像 /uploads/
をマウントし、事実上、アプリのロジックを画像ストレージから分離しました。
この演習では、次の作業を行います。
- 第 6 章(ストレージ)の演習を正常に完了している。
- 画像アップロード用の GCS バケットを用意します。ユーザーがアプリで写真をアップロードすると、その写真がバケットに転送されます。
Cloud Functions(Python)を設定する
イベント ドリブン アプリケーションの実装方法について疑問に思ったことはありませんか?次のようなものです。
- <event> が発生したとき => メールを送信する
- <event> が発生したとき => <condition> が true の場合、データベースを更新します。
イベントは、BigQuery で使用可能な新しいレコード、GCS のフォルダで変更された新しいオブジェクト、Pub/Sub のキューで待機中の新しいメッセージなど、さまざまなものがあります。
Google Cloud は、これを実現するために複数のパラダイムをサポートしています。特に重要なのは次のとおりです。
- EventArc。GCS イベントを受信する方法をご覧ください。DAG を作成し、Cloud で if-then-else に基づいてアクションをオーケストレートするのに最適です。
- Cloud Scheduler。たとえば、Cloud の深夜の cron ジョブに最適です。
- Cloud Workflows。Event Arc と同様に、次のことができます。
- Cloud Run Functions(一般に
lambdas
と呼ばれます)。 - Cloud Composer: 基本的には Apache Airflow の Google バージョンで、DAG にも最適です。
この演習では、Cloud Functions を詳しく調べて、素晴らしい結果を実現します。また、オプションの演習も用意しています。
サンプルコードは .solutions/
で提供されています。
Cloud Functions を設定する(🐍 Python)
私たちは非常に野心的な GCF を作成しようとしています。
- GCS に新しいイメージが作成された場合...(おそらく、誰かがアプリにアップロードしたためですが、それだけではありません)
- .. Gemini を呼び出して説明を取得し、画像の説明(テキスト形式)を取得します ..(MIME をチェックして、PDF、MP3、テキストではなく画像であることを確認するとよいでしょう)
- .. この説明で DB を更新します。(これには、
images
テーブルにdescription
列を追加するための DB のパッチ適用が必要になる場合があります)。
DB にパッチを適用して、description
を画像に追加します
- Cloud SQL Studio を開きます。
- Images DB のユーザーとパスワードを入力します
- この SQL を挿入して、画像の説明用の列を追加します。
ALTER TABLE images ADD COLUMN description TEXT;
これで完了です。次のコマンドを実行して、動作を確認します。
SELECT * FROM images;
新しい説明列が表示されます。
Gemini の f(x) を記述します。
注: この関数は、実際には Gemini Code Assist の支援機能を使用して作成されました。
注: この関数を作成すると、IAM 権限エラーが発生することがあります。一部は、以下の「考えられるエラー」の段落で説明しています。
- API を有効にする
- https://console.cloud.google.com/functions/list に移動します。
- [関数を作成] をクリックします。
- API ウィザードから API を有効にする:
GCF は、UI またはコマンドラインから作成できます。ここではコマンドラインを使用します。
コードの例は .solutions/
で確認できます。
- コードをホストするフォルダ(例: gcf/)を作成します。フォルダに入ります。
requirements.txt
ファイルを作成します。
google-cloud-storage
google-cloud-aiplatform
pymysql
- Python 関数を作成します。サンプルコード: gcf/main.py。
#!/usr/bin/env python
"""Complete this"""
from google.cloud import storage
from google.cloud import aiplatform
import vertexai
from vertexai.generative_models import GenerativeModel, Part
import os
import pymysql
import pymysql.cursors
# Replace with your project ID
PROJECT_ID = "your-project-id"
GEMINI_MODEL = "gemini-1.5-pro-002"
DEFAULT_PROMPT = "Generate a caption for this image: "
def gemini_describe_image_from_gcs(gcs_url, image_prompt=DEFAULT_PROMPT):
pass
def update_db_with_description(image_filename, caption, db_user, db_pass, db_host, db_name):
pass
def generate_caption(event, context):
"""
Cloud Function triggered by a GCS event.
Args:
event (dict): The dictionary with data specific to this type of event.
context (google.cloud.functions.Context): The context parameter contains
event metadata such as event ID
and timestamp.
"""
pass
- 関数を push します。gcf/push-to-gcf.sh のようなスクリプトを使用できます。
注 1。正しい値で ENV を取得するか、上に追加してください(GS_BUCKET=blah
、..)。
注 2。これにより、すべてのローカルコード(.
)が push されます。コードを特定のフォルダで囲み、.gcloudignore
をプロのように使用して、巨大なライブラリの push を回避してください。(例)。
#!/bin/bash
set -euo pipefail
# add your logic here, for instance:
source .env || exit 2
echo "Pushing ☁️ f(x)☁ to 🪣 $GS_BUCKET, along with DB config.. (DB_PASS=$DB_PASS)"
gcloud --project "$PROJECT_ID" functions deploy php_amarcord_generate_caption \
--runtime python310 \
--region "$GCP_REGION" \
--trigger-event google.cloud.storage.object.v1.finalized \
--trigger-resource "$BUCKET" \
--set-env-vars "DB_HOST=$DB_HOST,DB_NAME=$DB_NAME,DB_PASS=$DB_PASS,DB_USER=$DB_USER" \
--source . \
--entry-point generate_caption \
--gen2
注: この例では、generate_caption
が呼び出されるメソッドになり、Cloud Functions は関連するすべての情報(バケット名、オブジェクト名など)を含む GCS イベントを渡します。このイベントの Python 辞書をデバッグしてください。
関数のテスト
単体テスト
この関数には多くの可変要素があります。すべての単一テストを実行できるようにしたい場合があります。
例については、gcf/test.py をご覧ください。
Cloud Functions UI
また、UI で関数を調べてみてください。すべてのタブを調べることをおすすめします。特に Source
(私のお気に入り)、Variables
、Trigger
、Logs
は重要です。Logs
では、エラーのトラブルシューティングに多くの時間を費やすことになります(このページの下部にある考えられるエラーもご覧ください)。また、Permissions
も必ず確認してください。
E2E テスト
関数を手動でテストする時間です。
- アプリに移動してログインします
- 写真をアップロードします(大きすぎないようにしてください。大きな画像で問題が発生した例があります)。
- UI で写真がアップロードされていることを確認します。
- Cloud SQL Studio で、説明が更新されていることを確認します。ログインして、クエリ
SELECT * FROM images
を実行します。
そして、すでに高い効果が確認されています。フロントエンドを更新して、その説明を表示することもできます。
PHP を更新して [省略可]を表示
アプリが動作することは確認済みです。ただし、ユーザーもその説明を確認できるようにしてほしいです。
index.php
に説明を追加するのに、PHP の専門家である必要はありません。このコードは次の処理を行います(このコードも Gemini が作成してくれました)。
<?php if (!empty($image['description'])): ?>
<p class="font-bold">Gemini Caption:</p>
<p class="italic"><?php echo $image['description']; ?></p>
<?php endif; ?>
このコードは、foreach
内の任意の場所に配置してください。
次のステップでは、Gemini Code Assist のおかげで、より見やすい UI バージョンも表示されます。整形されたバージョンは次のようになります。
まとめ
GCS に新しいオブジェクトが追加されるとトリガーされる Cloud Functions を作成しました。この関数は、人間が画像の内容を認識するのと同じように、画像の内容を認識して、DB を自動的に更新できます。すごい!
次のステップ: 同じ理由で、2 つの優れた機能を実現できます。
[省略可] Cloud Functions を追加する [自由回答形式]
他にもいくつかの機能が考えられます。
📩 メール トリガー
写真を送信するたびにメールを送信するメール トリガー。
- 頻繁に発生しているか?さらに制約を追加します。Gemini コンテンツに「nude(ヌード)」「nudity(ヌード)」「violent(暴力)」という単語が含まれている大きな画像。
- この場合は
EventArc
を確認することをおすすめします。
🚫 不適切な写真を自動的に管理する
現在、人間の管理者が画像を「不適切」として報告しています。Gemini に手間のかかる作業を任せて、スペースを管理してもらうのはどうでしょうか?前の関数で学習したように、不適切なトリガー コンテンツにフラグを設定し、DB を更新するテストを追加します。つまり、基本的には前の関数を取得し、プロンプトを変更して、回答に基づいて DB を更新します。
注意。生成 AI の出力は予測できません。Gemini の「クリエイティブ出力」が「レールに乗っている」ことを確認します。0 ~ 1 の信頼スコアや JSON などの決定論的な回答を求めることができます。これは、pydantic
や langchain
などの Python ライブラリを使用したり、Gemini の構造化出力を使用したりするなど、さまざまな方法で実現できます。
ヒント。複数の関数を使用することも、JSON 形式の回答を強制する単一のプロンプトを使用することもできます(上記の「Gemini 構造化出力」でうまく機能します)。
この画像を生成するためのプロンプトは何ですか?
{
"description": "This is the picture of an arrosticino",
"suitable": TRUE
}
プロンプトに追加のフィールドを追加して、メリットがあるかどうかなどの分析情報を取得できます。悪い点について教えてください。この場所をご存知ですか?テキストはありますか(OCR がかつてないほど簡単になりました):
goods
: 「おいしそうな食べ物ですね」bads
: 「不健康な食べ物に見える」OCR
: 「賞味期限: 2024 年 11 月 10 日」location
: "Pescara, Lungomare"
通常は N 個の結果に対して N 個の関数を用意する方が良いのですが、1 つの関数で 10 個の結果を処理する方がやりがいがあります。詳しくは、Riccardo の記事をご覧ください。
発生する可能性のあるエラー(主に IAM / 権限)
このソリューションを初めて開発したとき、IAM 権限に関する問題が発生しました。ここでは、共感と修正方法のアイデアを提供するために、それらを追加します。
エラー: サービス アカウントに十分な権限がありません
- GCS バケットをリッスンする GCF 関数をデプロイするには、図のように、ジョブに使用するサービス アカウントに適切な権限を設定する必要があります。
EventArc API を有効にする必要もあります。完全に利用可能になる数分前に有効にしてください。
エラー: Cloud Run 起動元が見つからない
- GCF の権限設定の UI からの別のコメントは次のとおりです(Cloud Run 起動元ロール)。
このエラーは、イメージで fix-permissions.sh に似たコマンドを実行することで解決できます。
この問題については、https://cloud.google.com/functions/docs/securing/authenticating をご覧ください。
エラー: メモリの上限を超えました
初めて実行したとき、ログに「Memory limit of 244 MiB exceeded with 270 MiB used. メモリ上限の引き上げを検討してください。https://cloud.google.com/functions/docs/configuring/memory をご覧ください。」もう一度、GCF に RAM を追加します。これは UI で簡単に実行できます。以下は、考えられるバンプの例です。
また、Cloud Run デプロイ スクリプトを修正して MEM/CPU を増やすこともできます。この処理には時間がかかります。
エラー: PubSub Published
GCF v1 でトリガーを作成すると、次のエラーが 1 回発生しました。
この問題も、[IAM] に移動してサービス アカウントに「Pub/Sub パブリッシャー」ロールを付与することで簡単に解決できます。
エラー: Vertex AI が使用されていません
このエラーが表示された場合:
Permission Denied: 403 Vertex AI API has not been used in project YOUR_PROJECT before or it is disabled. https://console.developers.google.com/apis/api/aiplatform.googleapis.com/overview?project=YOR_PROJECT にアクセスして有効にしてください。
Vertex AI API を有効にするだけです。必要な API をすべて有効にする最も簡単な方法は次のとおりです。
- https://console.cloud.google.com/vertex-ai
- [すべての推奨 API を有効化] をクリックします。
エラー: EventArc トリガーが見つかりません。
このエラーが発生した場合は、関数を再デプロイしてください。
エラー: 400 サービス エージェントがプロビジョニング中である
400 個のサービス エージェントをプロビジョニングしています(https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents)。指定された Cloud Storage ファイルを読み取るには、サービス エージェントが必要です。数分後にもう一度お試しください。
この場合は、しばらく待つか、Google 社員にお問い合わせください。
10. モジュール 8: 可用性 SLO を作成する
この章では、次のことを目指します。
- SLI の作成
- SLI に基づく SLO の作成
- SLO に基づくアラートの作成
Riccardo は Google Cloud の SRE / DevOps 領域で働いているため、これは著者にとって非常に重要なトピックです。
(自由回答)このアプリの SLI と SLO を作成する
アプリがダウンしたときに通知されないアプリは、役に立ちません。
SLO とは
偶然ですね。Google は SLO を発明しました。詳細については、以下をご覧ください。
- SRE Book - 第 2 章 - SLO の実装。(👉 その他の SREbooks)
- SLO の技術(素晴らしい動画)。サービスに最適な SLO を作成する方法について詳しく学ぶことができる、素晴らしいトレーニングです。
- Coursera の SRE コース。私も貢献しました。
ステップ 1: 可用性の SLI/SLO を作成する
まず、最も簡単で、おそらく最も重要な測定対象である可用性 SLO から始めましょう。
幸いなことに、Cloud Run には Istio のおかげで、SLO サポートが組み込まれています。
アプリが Cloud Run にある場合は、30 秒で簡単に実現できます。
- Cloud Run ページに移動します。
- アプリをクリックまたは選択します。
- [
SLOs
] タブを選択します。 - [+ SLO を作成] をクリックします。
- 利用可能、リクエストベース
- 続行
- カレンダーの月 / 99%。
- [SLO を作成] をクリックします。
ステップ 2: この SLO のアラートを設定する
2 つのアラートを作成することをおすすめします。
- バーンレートが低い(「Slowburn」)もので、メールでアラートを送信します(優先度の低いチケットをシミュレートします)。
- バーンレートが高い(「Fastburn」)アラートを SMS で送信する(優先度の高いチケット / ページャーをシミュレート)
以前の SLO tab
に移動します。
次の操作を 2 回行います。
- [SLO アラートを作成](右側のプラス記号付きのベルのボタン)をクリックします。
- ルックバック期間、バーンレートのしきい値:
- [高速]。1 回目:
60
分 /10
回 - [SLOW]。2 回目:
720
分 /2
回 - 通知チャンネル: [通知チャンネルを管理] をクリックします。
- まず、[Email] -> [Add new] -> ..
- 次に、[SMS] -> [新規追加] -> スマートフォンで確認します。
- ヒント: 名前には絵文字を使用することをおすすめします。デモに最適です。
- 完了したら、右上の大きな X をクリックします。
- 電話を最初に選択し(速い)、メールを次に選択します(遅い)。
- 次のようなサンプル ドキュメントを追加します。
[PHP Amarcord] Riccardo told me to type sudo reboot or to check documentation in http://example.com/playbooks/1.php but I guess he was joking
。
ビンゴ!
最終結果
可用性について 1 つの SLO と 2 つのアラートが機能し、メールと電話にアラートが送信されるようになったら、この演習は完了です。
必要に応じて、レイテンシ(強く推奨します)や、より複雑なものを追加できます。レイテンシについては、妥当と思われるレイテンシを選択します。判断に迷った場合は、200 ミリ秒を選択します。
11. 次のステップ
すべて完了したのに、何が足りないのですか?
参考情報:
Gemini を試す
Gemini には次の 2 つのフレーバーがあります。
- Vertex AI。第 7 章(GCF+Gemini)で説明したように、GCP と密接に連携する「エンタープライズ方式」です。すべての認証が魔法のように機能し、サービスが美しく相互接続されます。
- Google AI。「Consumer way」こちらから Gemini API キーを取得し、既存のワークロード(独自の作業、他のクラウド、ローカルホストなど)に結び付けることができる小さなスクリプトの作成を開始します。API キーを置き換えるだけで、コードが魔法のように機能し始めます。
(2)については、ご自身のペット プロジェクトで試してみることをおすすめします。
UI Lifting
UI は苦手です。Gemini は違います。単一の PHP ページを取得して、次のように記述します。
I have a VERY old PHP application. I want to touch it as little as possible. Can you help me:
1. add some nice CSS to it, a single static include for tailwind or similar, whatever you prefer
2. Transform the image print with description into cards, which fit 4 per line in the canvas?
Here's the code:
-----------------------------------
[Paste your PHP page, for instance index.php - mind the token limit!]
これは、Cloud Build を 1 回実行するだけで 5 分以内に簡単に取得できます。:)
Gemini の回答は完璧でした(つまり、何も変更する必要がありませんでした)。
著者の個人用アプリの新しいレイアウトは次のとおりです。
注: コードは画像として貼り付けられています。これは、コードをコピーするのではなく、独自のクリエイティブな UI/フロントエンドの制約を使用して Gemini にコードを記述してもらうことをおすすめするためです。後で ごくわずかな変更を加えるだけで済みます。
セキュリティ
このアプリの適切な保護は、この 4 時間のワークショップの目標ではありません。このワークショップの完了時間が 1 ~ 2 桁増えるためです。
ただし、このトピックは非常に重要です。SECURITY
にアイデアをまとめました。
12. 完了
おめでとうございます 🎉🎉🎉。Google Cloud を使用して、レガシー PHP アプリケーションのモダナイズに成功しました。
この Codelab では、次のことを学習しました。
- Google Cloud SQL にデータベースをデプロイする方法と、既存のデータベースを移行する方法。
- Docker と Buildpacks を使用して PHP アプリケーションをコンテナ化し、そのイメージを Google Cloud Artifact Registry に保存する方法
- コンテナ化されたアプリを Cloud Run にデプロイして Cloud SQL で実行する方法
- Google Secret Manager を使用して機密性の高い構成パラメータ(DB パスワードなど)を秘密裏に保存/使用する方法
- Google Cloud Build を使用して CI/CD パイプラインを設定し、GitHub リポジトリにコードが push されるたびに PHP アプリを自動的にビルドしてデプロイする方法。
- Cloud Storage を使用してアプリリソースを「クラウド化」する方法
- サーバーレス テクノロジーを活用して、アプリコードを変更せずに Google Cloud 上に優れたワークフローを構築する方法。
- 適切なユースケースで Gemini のマルチモーダル機能を使用します。
- Google Cloud 内で SRE の原則を実装する
これで、Google Cloud を使用したアプリケーション モダナイゼーションの旅を始める準備が整いました。
🔁 フィードバック
このワークショップについてのご意見、ご感想がございましたら、こちらのフィードバック フォームにご記入ください。
フィードバックや、特に自信のあるコードの PR もお待ちしております。
🙏 よろしくお願いいたします。
このソリューションの作成とテストにご協力いただいた Datatonic の Mirko Gilioli 氏と Maurizio Ipsale 氏に感謝いたします。