AWS App RunnerでのNest.js APIサーバーのPort変更と対応メモ

社内検証用のNest.js APIサーバーをAWSのApp Runner上に置いていたのですが、開発環境の変更によりPortを変更する必要が生じました。ソースコードを変更してApp Runner側のPort設定も変えるだけやろと思っていたら上手くいかなかったのでその時の原因調査と対応メモ。

はじめに

まず自分のApp Runnerに関する前提知識としては以下のような状態でした。

  • App Runner触ったことない
  • App Runnerのコンソール見るのも今回が初めて
  • 「App Runnerフルマネージドだし一回環境作っちゃえばあとはよしなにやってくれるから超便利」くらいの知識しかない

なので、今回のPort変更のついでにApp Runner少し触ってみるかくらいの軽い気持ちで対応を開始しました。

やりたいこと

  • Nest.jsのappサーバーのPortを3000から8000へ変更したい
  • App RunnerのPort設定も3000から8000へ変更したい

発生した問題と対応

  1. App RunnerのPort設定変更の試み

    とりあえずまずApp RunnerのPort設定を8000に変更してみましたが、失敗してロールバックされました。

    ログを確認しようとしたのですが、App Runnerには複数のログタイプがあり、どれを見るべきか最初はよくわからなかったです。
    最終的にApp Runnerのイベントログを確認すればいいことが判明。

    確認したところ、App Runnerは新しいPort 8000でヘルスチェックを試みていたが、アプリケーション側はまだPort 3000だったため、疎通エラーが発生していました。

    [AppRunner] Service update started.
    [AppRunner] Service status is set to OPERATION_IN_PROGRESS.
    [AppRunner] Provisioning instances and deploying image.
    [AppRunner] Performing health check on path '/' and port '8000'.
    [AppRunner] Your application stopped or failed to start. See logs for more information.  Container exit code: 1
    
  2. アプリケーション側のPort変更の試み

    じゃあアプリ側のPortも8000にしてみるかということで、Port 8000に変更してECRにイメージをpush。

    今度はApp Runner側でデプロイエラー発生しロールバックされました。

    ログを確認します。
    アプリケーションログを確認すると、コンテナ内ではサーバーは起動している様子。
    イベントログを確認すると、Port 3000との疎通ヘルスチェックでエラーになっていました。

    [AppRunner] Deployment started.
    [AppRunner] Service status is set to OPERATION_IN_PROGRESS.
    [AppRunner] Successfully copied the image from ECR.
    [AppRunner] Provisioning instances and deploying image.
    [AppRunner] Performing health check on path '/' and port '3000'.
    [AppRunner] Your application stopped or failed to start. See logs for more information.  Container exit code: 1
    [AppRunner] Deployment failed. For details, see service logs.
    

    つまりApp Runnerの設定はPort 3000なのに、アプリ側はPort 8000だからエラー。
    1の対応でApp Runner側の設定をPort 8000に変更したけど、エラーでロールバックされて設定がPort 3000に戻っていたためでした。

  3. 再試行とApp Runnerの仕様理解

    じゃあ再度App Runner側の設定をPort 8000にしたらどうなるのかと思い変更してみました。

    やっぱり疎通エラーでロールバックされます。

    つまりアプリ側もPort 8000のイメージはpushしたものの、エラーになってApp Runnerの環境はロールバックされているので、App Runner上で動いているイメージは正常に動作するPort 3000のものになっていました。

    どちらかのPortを8000に変更しても、もう片方のPortが3000に戻ってしまっている状態なので、ヘルスチェックが通らずPortの設定は変更できないという状態です。

    App Runnerがフルマネージドでアプリが正常に立ち上がることを常に担保してくれるが故の事象でした。

実際の解決策

  • アプリケーション側でPORT環境変数を設定
  • App Runner側の設定はPort 3000のままに
  • アプリケーションが開発環境用にデフォルトでPort 8000を使用し、prod用のDockerfileにPORT環境変数3000を追加して、本番ではApp Runnerの設定と合うように変更
-await app.listen(3000);
+await app.listen(process.env.PORT || 8000);
+ENV PORT 3000

まとめ

環境変数を使用することは基本的なアプローチではありますが、なぜエラーになるのか?という根本原因を色々触りながら探っていくことで、App Runnerの仕様についての理解を深めることができたと思います。公式ドキュメントにはない細かい動きは現状ログを確認して理解していくしかないですね。

最後に

IOでは常に最新技術のキャッチアップと検証を行っています!
どんどん新しい技術が出てくるこの業界で自分の力を試したい方は、
是非以下からご応募宜しくお願いします!
まずはカジュアルに話を聞いてみたいという方でも大歓迎です!

herp.careers