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 ドキュメント 内部サービスへのアクセス

■関連サイト

過去記事アーカイブ

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