😩

AWS ECS上で500(Internal Server Error)エラーが出た時の対処法

2024/06/19に公開

デプロイ関連で結構詰まったので、記事として残しておきます。
他の方の参考になれば幸いです。

きっかけ

ECSにしばらくぶりに、変更内容をデプロイしてみると...
実行ステータスに "デプロイ失敗" の文字が。

あわててタスクのログを見に行くと、ロードバランサーのヘルスチェックが通らないために実行したコンテナがドレインされてしまうようです。

 "GET / HTTP/1.1" 500 13492 "-" "ELB-HealthChecker/2.0"

以上のログから、原因を探っていきます。

原因調査の流れ

前節のログの内容からステータスコード500でレスポンスが返ってきていることがわかるます。
https://e-words.jp/w/500エラー.html

アプリケーション(今回はLaravel)の設定が間違っている可能性があるため、
コンテナ内に入って、ログ(laravel.log)を確認していきます。

コンテナ内に入る手段には、ECS Execを使用しました。
やり方は、以下の記事を参考にしてください。
https://zenn.dev/nenenemo/articles/9f66924801114c

laravel.logをcatコマンドで確認していきます。。。

No application encryption key has been specified. {"exception":"[object] (Illuminate\Encryption\MissingAppKeyException(code: 0): No application encryption key has been specified. at /var/www/html/vendor/laravel/framework/src/Illuminate/Encryption/EncryptionServiceProvider.php:79)

どうやら.envファイルの暗号化キー(.envのAPP_KEY項目)が設定されていないようです。
.envも確認すると、APP_NAMEのみ設定されている状態でした。

どうしてこうなった

GitHub Actionsで、ECR、ECSへの操作を行っていたのですが、
その前段階で.envの内容を更新する処理を入れていました。
(ローカル用とデプロイ用で使い分けるため)
その処理が、下記の通りになります。

- name: Renew envProductionFile
id: renew-env
    run: |
      sed -i 's|\[DB_USERNAME\]|${{ env.AWS_DB_USERNAME }}|g' ./product-app/.env.production
      sed -i 's|\[DB_HOST\]|${{ env.AWS_DB_HOST }}|g' ./product-app/.env.production
      sed -i 's|\[DB_DATABASE\]|${{ env.AWS_DB_DATABASE }}|g' ./product-app/.env.production
      sed -i 's|\[DB_PASSWORD\]|${{ env.AWS_DB_PASSWORD }}|g' ./product-app/.env.production
      echo "::set-output name=content::$(cat ./product-app/.env.production)"

- name: Update .env file
    run: |
      echo "${{ steps.renew-env.outputs.content }}" > ./product-app/.env
      cat ./product-app/.env

はい、見事にcpコマンドを忘れていますね。。。
どおりでうまくいかないわけだ(笑)
コピーの処理を追加して、合わせて修正しておきます。

- name: Copy .env.production to .env
    run: cp ./product-app/.env.production ./product-app/.env

対処法

.env内に「APP_KEY=」という表記がある場合は、
コンテナ内で以下のコマンドを実行すると暗号化キーが生成されて、解決します。

$ php artisan key:generate //暗号化キーの生成
Application key set successfully.

$ php artisan config:clear //キャッシュのクリアで設定を反映
Configuration cache cleared!

私の場合は、そもそも項目がなかったので、
ローカルで必要な設定情報を入力した後、ECRにプッシュ→ECSに再デプロイで解決しました。

Discussion