grasys blog

Cloud RunにデプロイしたLaravelアプリケーションをCloud Schedulerで定期実行

文●tomatsuri/grasys 編集● ASCII

  • この記事をはてなブックマークに追加
  • 本文印刷

本記事はgrasys が提供する「grasys blog」に掲載されたCloud RunにデプロイしたLaravelアプリケーションをCloud Schedulerで定期実行」を再編集したものです。

 こんにちは、tomatsuriです。

 Cloud Schedulerを触ってみたいという衝動に駆られ、Cloud RunにLaravelアプリケーションをデプロイし、Cloud Schedulerで定期実行するサンプルを作成してみました。

Laravelアプリケーションの作成

 まず、Cloud Schedulerから定期的にアプリケーションが実行されていることを確認するために、[/batch]にGETリクエストをしたらログに"batch executed.“と出力するだけの簡単な機能を用意しておきます。

 Cloud Runは標準出力に出力したログはCloud Loggingによって自動的に取得されるため(脚注1)、Laravelから標準出力にログを出力するために[config/logging.php]のchannelsに以下を追加します。

'stdout' => [
    'driver' => 'monolog',
    'handler' => StreamHandler::class,
    'with' => [
        'stream' => 'php://stdout',
    ],
],

 (Laravel8系を使用)

 あとは環境変数のLOG_CHANNELをstdoutに書き換えればOKです。 環境変数はCloud Run上で設定が可能です(脚注2)。

Dockerイメージの作成

 以下のようなDockerfileをプロジェクトのルートに用意します。 Cloud RunにLaravelをデプロイする方法としてApacheを使用している例をいくつか見たので、 今回はnginxでやってみました。

FROM php:8.0-fpm-alpine

RUN apk add --no-cache nginx wget

RUN mkdir -p /run/nginx
COPY docker/nginx.conf /etc/nginx/nginx.conf

RUN mkdir -p /app
COPY . /app

RUN sh -c "wget http://getcomposer.org/composer.phar && chmod a+x composer.phar && mv composer.phar /usr/local/bin/composer"
RUN cd /app && \
    /usr/local/bin/composer install --no-dev

RUN chown -R www-data: /app

CMD sh /app/docker/startup.sh

 nginx.confとstartup.shはこちら。 ドキュメント(脚注3)に従い、PORT環境変数で定義されたポートをリッスンするように構成しています。

worker_processes  1;

events {
    worker_connections  1024;
}
http {
    include mime.types;
    keepalive_timeout 65;

    server {
        listen LISTEN_PORT default_server;
        server_name _;
        root /app/public;
        index index.php;
        charset utf-8;
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }

        location = /favicon.ico { access_log off; log_not_found off; }
        location = /robots.txt  { access_log off; log_not_found off; }
        access_log /dev/stdout;
        error_log /dev/stderr;

        client_max_body_size 100m;

        location ~ \.php$ {
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
        }
    }
}

daemon off;
#!/bin/sh

sed -i "s,LISTEN_PORT,$PORT,g" /etc/nginx/nginx.conf

php-fpm -D

nginx

 startup.shは[chmod a+x docker/startup.sh]でパーミッションを変更しておきます。

 これらはプロジェクトのルートにdockerフォルダを作成し、その中に配置しています。

 Dockerfile、nginx.conf、startup.shが用意できたら[☒docker build -t laravel-batch01 . ]を実行してビルドします。

 ビルドが完了したら、[docker run -e PORT=80 -p 8080:80 laravel-batch01]で起動し、localhost:8080でアクセスして確認してみましょう。

Container Registryへイメージをpush

 まずはビルドしたイメージにレジストリ名をタグ付けします(脚注4)。

docker tag laravel-batch01 asia.gcr.io/[PROJECT-ID]/laravel-batch01

 次に、Container Registryへアクセスするための認証を行います。今回は推奨とされているgcloud 認証情報ヘルパーを使用します(脚注5)。

 ユーザーまたはサービスアカウント(推奨)で認証を行い、[gcloud auth configure-docker]でgcloudをDockerの認証ヘルパーとして設定します。

 これでタグ付きイメージをContainer Registryにpushできるようになりました。

docker push asia.gcr.io/[PROJECT-ID]/laravel-batch01

 でpushし、Cloud ConsoleのContainer Registry上で確認できればOKです。

Cloud Runを作成

 laravel-batch01という名前のCloud Run サービスを作成します。

 Cloud Console上でCloud Runのページにアクセスし、サービスの作成へ進みます。

 「サービスの最初のリビジョンの構成」のコンテナイメージのURLは、先程pushしたイメージを選択します。

 Container Registryのイメージ詳細から直接作成することも可能です。

 最後の「このサービスをトリガーする方法の構成」では、 Ingressは「すべてのトラフィックを許可する」を選択します。

 現時点(2021/05/14)ではCloud Schedulerから内部サービスに対してhttpリクエストすることはできません(脚注6)。

 認証は「認証を必要とする」を選択し、作成します。

Cloud SchedulerからCloud Runを起動するためのサービスアカウントを作成

 このままCloud SchedulerからCloud Runへhttpリクエストをしても、権限がなく失敗してしまいます。

 そこで、作成したCloud Runを起動する権限を持つサービスアカウントを作成し、それを使用してCloud SchedulerからCloud Runへリクエストするように設定します。

 ここではlaravel-batch01-invokerという名前のサービスアカウントを作成し、以下のコマンドで権限を付与します。

gcloud run services add-iam-policy-binding laravel-batch01 \
    --member=serviceAccount:[サービスアカウントのメールアドレス] \
    --role=roles/run.invoker

 Cloud Run詳細ページの権限タブを開き、Cloud Run 起動元の権限を持つサービスアカウントが追加されていればOKです。

Cloud Schedulerの設定

 「ジョブを定義する」で名前、頻度(unix-cron形式)、タイムゾーンを設定します。

 「ジョブのターゲットを構成する」で、どこにどのようなリクエストを送信するのかを設定します。 今回は以下のようになります。

 ・ターゲットタイプ:HTTP
 ・URL:Cloud Runにデプロイしたアプリケーションのエンドポイント
 ・HTTPメソッド:GET

 Authヘッダーは「OIDC トークンを追加」を選択し、先程作成したサービスアカウント(laravel-batch01-invoker)のメールアドレスを入力します。

 「詳細設定を構成する」でリトライ回数などを設定できますが、今回はデフォルトのままにします。

 ジョブを作成したら、ジョブが実行されるまで待ってもよいですし、「今すぐ実行」ボタンで任意のタイミングで実行することもできます。

実行結果

 ジョブの結果が「成功」となり、Cloud Runのログにアプリケーションで実装したログのメッセージが出力されていれば完了です。

おわり

 Cloud Run、Cloud Schedulerを使用して手軽にバッチ処理のサンプルを作成できました。

 ちなみにCloud Scheduler料金は実行単位ではなくジョブ単位です。

 請求アカウント毎(プロジェクト毎ではない)に3ジョブの無料枠があり、課金対象となってもジョブあたり$0.10/月とお手頃です。

 今後はCloud Schedulerのhttp以外のターゲットを使ってみたり、他のサービスを使用したバッチ処理のアーキテクチャなど色々試していけたらなと思います。

脚注

1.Cloud Run ドキュメント ログの記録と表示 コンテナログを作成する

2.Cloud Run ドキュメント 環境変数の使用

3.Cloud Run ドキュメント コンテナポートの構成

4.Container Registry ドキュメント ローカル イメージにレジストリ名でタグ付けする

5.Container Registry ドキュメント gcloud 認証情報ヘルパー

6.Cloud Run ドキュメント 内部サービスへのアクセス

■関連サイト

過去記事アーカイブ

2022年
01月
02月
03月
04月
05月
06月
07月
2021年
03月
04月
05月
06月
07月
08月
09月
10月
11月
12月
2020年
04月
05月
08月
09月
10月
11月
12月
2018年
09月
2017年
06月
2014年
07月