【AWS / CodeBuild / Docker】You have reached your pull rate limit. You may increase the limit by authenticating and upgrading

◆問題

CodePipelineでECSのFargateにDeploy時、DockerHubのRateLimitに引っかかった。何度かやると成功する時もあるけど、正直何度も実行するのが面倒なので渋々対策することに。

◆解決方法

基本的には以下のページにあった内容の通りで行けた。

fu3ak1.hatenablog.com

1点付け加えるとすれば、CodeBuildの実行ロールでSSMの読み込み権限をPolicyアタッチしないと権限エラーとなる。アタッチするPolicyは以下の通り。

f:id:daylambsbecomelions:20220410111521p:plain

【AWS / Laravel】The stream or file "/var/www/html/storage/logs/laravel.log" could not be opened in append mode: failed to open stream: Permission denied

◆問題

ECSのFargateでLaravelのプロジェクトを立ち上げた時に掲題のエラーが発生。storageのフォルダはDockerfileで以下の通り権限変更しており、同じDockerイメージでローカルで立ち上げた時は何事もなく動くのになぜ??

RUN chmod -R 775 storage

◆原因

色々試してみて分かったのだが、どうやらルートからの絶対パスで書かないとダメだったのと、AWS環境の場合はフォルダの所有者も「www-data」に変更する必要がある模様。

◆解決方法

自分のケースの場合は「/var/www/html」配下にLaravelのプロジェクトソースを展開しているので、以下のような形でDockerfile内の権限部分を変更するとうまくいった。

RUN chmod -R 775 /var/www/html/storage && \
         chown -R www-data:www-data /var/www/html/storage

【AWS】CodePipelineでFargateのコンテナをDeploy時、ALBのTargetGroupが切り替わらない

◆問題

掲題の通りなのだが、自分でECSのFargateを立てて、CodePipelineでDeploy自動化を実装した際、ECS側のTargetGroupは切り替わるけど、ALBのTargetGroupが2つのうち1つ(Green側だけ)が固定となり切り替わらず、CodePipelineでGreen側にDeployした時だけ(2回に1回)しかリクエストが通らない問題が発生した。

◆原因

結局ALBへのTargetGroupの設定方法に問題があった。ALBとTargetGroupの紐付ける際、他にも色んなエラーが出ていたので、TargetGroupを個別で作成して、それをALBやECSのサービスに紐付けたりしていたけど、そのやり方が不味かった。

◆解決方法

正解のやり方として、ALBにTargetGroupが何も紐づいていない状態で、ECSのサービスを作成する際にALBを指定し、TargetGroupを新規作成して紐付ける必要があった。こういう方法でTargetGroupを紐づけることで、CodePipelineでDeployしてうまく切り替えられるようになり、想定通りの挙動になった。

f:id:daylambsbecomelions:20220409160724p:plain

【AWS】standard_init_linux.go:228: exec user process caused: exec format error 解決方法

MacでローカルでDockerイメージをビルドしてAWSのECRにpush。ECR上のイメージでECSのFargateを作って起動させた時に以下エラーが発生してコンテナが起動してはすぐに落ちるのループ状態に。

standard_init_linux.go:228: exec user process caused: exec format error

同じイメージでローカルでコンテナを起動したらうまく行くのになんでやねん!と思ってハマってたところ、以下のような記事を見つけた。

hikari-blog.com

はい、ここにある通り、M1チップ搭載のMacでDockerイメージをビルドしたのが原因でした。ビルドするマシンと実行するマシンのCPUアーキテクチャが異なると起動に失敗する、とのことです。Cloud9とかEC2, CodeBuildなど、AWSのサービス上でビルドすれば問題なかったようですが、まさかM1チップが原因だとは思いつきませんでした。

イメージビルド時にplatformを指定やれば、Macローカルビルドしたイメージでも問題なくコンテナ起動しました。

docker build --platform amd64 ./

【Laravel】ECS Fargate環境上のLaravelのログをCloudWatchに出力させる

Laravelかどうかに関係なく、ECS Fargate上のアプリのログをCloudWatchに表示させるには、ログを標準出力させればOK。Laravelの場合、config/logging.phpの「channel」部分を以下のように調整してあげるだけでよい。

   'channels' => [
        'stack' => [
            'driver' => 'stack',
            'channels' => ['single', 'stderr', 'stdout'],
            'ignore_exceptions' => false,
        ],

        'single' => [
            'driver' => 'single',
            'path' => storage_path('logs/laravel.log'),
            'level' => 'debug',
        ],

        'daily' => [
            'driver' => 'daily',
            'path' => storage_path('logs/laravel.log'),
            'level' => 'debug',
            'days' => 14,
        ],

        'slack' => [
            'driver' => 'slack',
            'url' => env('LOG_SLACK_WEBHOOK_URL'),
            'username' => 'Laravel Log',
            'emoji' => ':boom:',
            'level' => 'critical',
        ],

        'papertrail' => [
            'driver' => 'monolog',
            'level' => 'debug',
            'handler' => SyslogUdpHandler::class,
            'handler_with' => [
                'host' => env('PAPERTRAIL_URL'),
                'port' => env('PAPERTRAIL_PORT'),
            ],
        ],

        'ecs' => [
            'driver' => 'stack',
            'channels' => ['stderr', 'stdout'],
        ],

        'stdout' => [
            'driver' => 'monolog',
            'handler' => StreamHandler::class,
            'formatter' => env('LOG_STDERR_FORMATTER'),
            'formatter_with' => [
                'dateFormat' => '%Y-%m-%d %H:%M:%S'
            ],
            'with' => [
                'stream' => 'php://stdout',
            ],
        ],

        'stderr' => [
            'driver' => 'monolog',
            'level' => 'error',
            'handler' => StreamHandler::class,
            'formatter' => env('LOG_STDERR_FORMATTER'),
            'formatter_with' => [
                'dateFormat' => '%Y-%m-%d %H:%M:%S'
            ],
            'with' => [
                'stream' => 'php://stderr',
            ],
        ],

        'syslog' => [
            'driver' => 'syslog',
            'level' => 'debug',
        ],

        'errorlog' => [
            'driver' => 'errorlog',
            'level' => 'debug',
        ],

        'null' => [
            'driver' => 'monolog',
            'handler' => NullHandler::class,
        ],

        'emergency' => [
            'path' => storage_path('logs/laravel.log'),
        ],
    ],

何をしているかというと、デフォルト設定になっている「'stack'」に標準出力となる「'stderr'」と「'stdout'」を追加してあげているだけ。「'stdout'」に関してはLaravelのバージョンによっては記述がないかもしれないが、その場合は追記してやればよい。ちなみに「'single'」は見ての通りLaravelプロジェクトフォルダ内にログを出力する設定項目。この設定でCloudWatchにLaravelのログを出力させることができる。とっても簡単。

【Laravel】APIでBasic認証を使う

LaravelにはデフォルトでBasic認証の仕組みが実装されているので、基本的には「route/api.php」で以下のようにmiddlewareを追加してあげるだけ。

Route::get('sampleapi', 'SampleApiController@index')->middleware('auth.basic');

これだけで「User」テーブルの「email」と「password」でBasic認証が実装される。 f:id:daylambsbecomelions:20220103210815p:plain

ただ、この「User」テーブルを参照しに行くのに、configフォルダ内の「auth.php」の以下の部分を見ているので、

f:id:daylambsbecomelions:20220103211023p:plain

自分もそうなのだが、このUserモデルのパスを変更している場合、その変更したパスに合わせてここも調整してやる必要がある。 f:id:daylambsbecomelions:20220103211204p:plain

これでGood to Go

f:id:daylambsbecomelions:20220103211306p:plain

【Laravel】The stream or file "/var/www/html/storage/logs/laravel.log" could not be opened in append mode

storageフォルダは777に権限していて、welcome画面とかは普通に表示できているのに、apiのURLを呼び出すとなぜかこのエラーが発生。storageフォルダのオーナーを変更すると治るとのこと。

chown -R www-data:www-data storage