ECR+App RunnerをCDKデプロイする
[アップデート] AWS App Runner でついに AWS WAF がサポートされました | DevelopersIO
自分は圧倒的にLambdaマンだが、WAF対応もしたということで本番投入機会が増えていきそうなApp Runnerをキャッチアップしてみる。CDKで素振りする。
DockerのhttpdイメージをApp Runnerにデプロイしてみる。
環境
- M1 Mac Big Sur
- node 16.15.0
- typescript 5.0.2
- aws-cdk-lib 2.69.0
- constructs 10.1.281
- @aws-cdk/aws-apprunner-alpha 2.69.0-alpha.0
- cdk-docker-image-deployment 0.0.195
コード
aws-cdk-lib
以外のところで以下を利用する:
- ECRリポジトリ定義はcdk-docker-image-deploymentで楽できる
- App Runner定義は
@aws-cdk/aws-apprunner-alpha
で楽できる
両方とも公式もしくは準公式のパッケージなので採用で問題ないはず。
CDKコード:
// lib/app-runner-stack.ts import { Construct } from "constructs"; import * as cdk from "aws-cdk-lib"; import * as apprunner from "@aws-cdk/aws-apprunner-alpha"; import * as imagedeploy from "cdk-docker-image-deployment"; export class AppRunnerStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const repository = new cdk.aws_ecr.Repository(this, "httpdRepository", { repositoryName: "httpd-repository", removalPolicy: cdk.RemovalPolicy.DESTROY, }); new imagedeploy.DockerImageDeployment( this, "exampleImageDeploymentWithTag", { source: imagedeploy.Source.directory("./src/app-runner"), destination: imagedeploy.Destination.ecr(repository, { tag: "latest", }), } ); const service = new apprunner.Service(this, "apprunnerService", { source: apprunner.Source.fromEcr({ imageConfiguration: { port: 80 }, repository, tagOrDigest: "latest", }), }); new cdk.CfnOutput(this, "ServiceUrl", { exportName: "ServiceUrl", value: service1.serviceUrl, }); } }
Dockerfile:
# src/app-runner/Dockerfile FROM --platform=linux/amd64 httpd
M1 Macなので --platform=linux/amd64
を付ける必要がある(ないと後述のエラーが発生)。
ハマった点
上記コードに行き着くまでに結構ハマっている。App Runnerのデプロイ毎に数分かかることもあり、高速で試行を回しづらく時間を溶かしてしまった。
まず、最初にCDKデプロイしようとすると下記エラーに遭遇:
# CDKデプロイ時エラー Resource handler returned message: "null" (RequestToken: xxxxxxx-xxxxxxxxx-xxxxxxxx, HandlerErrorCode: null)
詳細な内容がなく、これだと原因がわからない。
こういうときはInfrastructure as Codeだけでなんとかしようとするのはやめてマネコンからリソースを作ってみるに限る、ということでマネコンからApp Runnerをデプロイ。
アプリケーションログにおいて以下のエラーが発生していることが判明:
# アプリケーションログ exec /usr/local/bin/httpd-foreground: exec format error
調べたところ、M1 MacでDockerイメージをビルドした際に起こる問題の模様。
【GCP】「exec user process caused: exec format error」というエラーを解決!【GKE】|HikariBlog
ここ数年Lambda一辺倒過ぎて最近(M1なんてもう最近でもないけど)のDocker事情をキャッチアップできてなかった。
最初は --platform=linux/amd64
を付けていなかったため、付与してこの点は解決。
- FROM httpd + FROM --platform=linux/amd64 httpd
で、またデプロイしようとすると再度エラー。今度はイベントログ:
# イベントログ [AppRunner] Deployment with ID : xxxxxxxxxxxxxxx failed. Failure reason : Health check failed. [AppRunner] Health check failed on port '8080'. Check your configured port number. For more information, read the application logs.
エラーによると「指定してるポート違うんじゃない?」とのことなので、見直して気づく。 8080
にしてしまっていたので 80
に直した。
- imageConfiguration: { port: 8080 } + imageConfiguration: { port: 80 },
以上でAWSマネコン操作でもCDKデプロイでも正常に起動できるようになった。