DockerImageにCLI実行モードを実装してECSでバッチ運用する

ECSで稼働するphp:fpm-alpineベースのPHP/Phalconで構築したアプリケーションイメージを流用して、ECSでバッチ処理をスケジュール実行するためのアーキ。

要件

  • 運用中のアプリケーションのイメージを流用できること。
  • スケジュール実行したあと、exit終了すること。
  • ログはCloudWatchLogに出力すること。

PhalconでCLI実行

エントリポイントとバッチ処理を実装する。下記のコードスニペットがそのまま使えました。 【PHP Phalcon】バッチ処理の実装とcronの設定

実行

# cliモードで起動
php /path/to/CLIエントリポイント.php \
&& className(→ ClassNameTaskクラス) \
&& action_name(→ actionNameActionメソッド) \
&& param1(→ メソッドの引数1) \
&& param2(→ メソッドの引数2)

Dockerイメージのフレキシブル運用

ENTRYPOINTCMDに応じて サーバー起動 or CLI実行 を切り替えるシェルスクリプトを用意して、docker run イメージ {コマンド上書き}あるいは、ecsのコマンド上書き設定で起動モードをスイッチ出来るようにする。



Dockerfile

...

# エントリポイントスクリプトをコピー
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# エントリポイントを設定
ENTRYPOINT ["/entrypoint.sh"]

# デフォルトでは FPM を起動
CMD ["fpm"]

entrypoint.sh

#!/bin/sh
set -e  # エラー時に停止

# 引数がない場合、または "fpm" の場合は PHP-FPM を起動
if [ "$1" = "fpm" ] || [ -z "$1" ]; then
    echo "Starting PHP-FPM..."
    exec php-fpm
fi

# "cli" の場合は、引数を `php` に渡して実行(CLIモード)
if [ "$1" = "cli" ]; then
    shift # `cli` を削除
    echo "Running PHP CLI..."
    exec php "$@"
fi

# それ以外のコマンドは直接実行
exec "$@"

実行

# サーバー起動モード
docker run -d イメージ
#=> php-fpm

# CLI実行でワンショット起動
docker run --rm イメージ cli /path/to/cli.php arg1 arg2
#=> php /path/to/cli.php arg1 arg2

# メンテコマンドでワンショット起動
docker run --rm イメージ ls -l
#=> ls -l

ECS

初見はいろいろと問題が出るので、新しいタスクの実行でデバッグしてからスケジュールされたタスクを構築することを推奨。



  • バッチ用のタスク定義を作成して、上記のイメージを指定する。
    • 起動タイプ(Fagate?EC2?)クラスタレイヤーの話なのにここで選ぶのかい?と混乱していたら、フォームを想定環境に最適化してくる親切設計であった。Amazon ECS 起動タイプ - Amazon Elastic Container Service
    • デバッグ、モニタリングためCloudWatchLogは必ずオン
  • クラスタ > スケジュールされたタスクでは主にタスク定義cron式および、コンテナの上書き > コマンドの上書きでCMDをCLI起動用に上書きする。
# だめ ひとつのコマンドとして認識される
# cli /path/to/cli.php className action_name
#=> /entrypoint.sh: exec: line X: cli /path/to/cli.php className action_name: not found

# OK カンマでCMD引数としてプロットしてくれる(説明どおり)
cli,/path/to/cli.php,className,action_name
#=> exec php /path/to/cli.php className action_name


つまずき

ResourceInitializationError

クラスター > タスクの状態より ResourceInitializationError: unable to pull secrets or registry auth: The task cannot pull registry auth from Amazon ECR: There is a connection issue between the task and Amazon ECR. Check your task network configuration. RequestError: send request failed caused by: Post "https://api.ecr.ap-northeast-1.amazonaws.com/": dial tcp 99.77.58.41:443: i/o timeout

イメージのpull → イメージのECRエンドポイントに接続できていない。 → タスクのサブネットがプライベートサブネットだったのでNAT/IGWの準備がなくECRに接続できない。パブリックサブネットに設置して通過。

Essential container in task exited

クラスター > タスクの状態より Essential container in task exited

プロセスが終了してexit状態なのでOK。CloudWatchLogで実行結果を確認する。

Share:

0 Comments: