ECR上のImage を AWS App Runner に CDK V2 でデプロイする
目次
AWS App Runner を使うと、Web Server を Docker コンテナにしておけば簡単にデプロイできます。 しかも、
- ECR の Image を更新したら自動で再デプロイしてくれる(自動にしないことももちろん可能)
- AutoScale や 独自ドメインの設定も可能
- アクセス数、Latency、Instance 数などのメトリクスも設定無しで見れる
- Application ログも自動で見られるようにしてくれる
といたれりつくせりです。ちょっとしたサービスをデプロイしたいときにはかなり重宝しそうです。
一度慣れれば手動設定でもそこまで面倒ではないですが、 今後何度もお世話になりそうなので、CDK V2 での書き方をまとめておきます。
Version
node
:16.13.1
aws-cdk
:2.8.0 (build 8a5eb49)
tsc
:4.5.4
書き方
import { Stack, StackProps } from "aws-cdk-lib";
import { Construct } from "constructs";
import { CfnService } from "aws-cdk-lib/aws-apprunner";
import { Role, ServicePrincipal } from "aws-cdk-lib/aws-iam";
import { StringParameter } from "aws-cdk-lib/aws-ssm";
// Deploy する Image の URI
const IMAGE_URI =
"99999999999.dkr.ecr.ap-northeast-1.amazonaws.com/my-web-app:release";
export class MyWebAppStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
let buildRole = this.createECRRole();
let taskRole = this.createTaskRole();
// AWS::AppRunner::Service
let appService = new CfnService(this, "MyWebApp", {
serviceName: "MyWebApp",
sourceConfiguration: {
authenticationConfiguration: {
accessRoleArn: buildRole.roleArn, // ECRにアクセスするときのRole?
},
imageRepository: {
imageIdentifier: IMAGE_URI,
imageRepositoryType: "ECR",
imageConfiguration: {
port: "8080", // Listen Port
runtimeEnvironmentVariables: [
// 実行時の環境変数
{ name: "PRODUCTION", value: "1" },
],
startCommand: "web", // コンテナ実行時のコマンド
},
},
autoDeploymentsEnabled: true, // 自動デプロイするか?
},
instanceConfiguration: {
cpu: "1 vCPU",
memory: "2 GB",
instanceRoleArn: taskRole.roleArn, // コンテナ実行時の Role
},
});
}
createECRRole(): Role {
let role = new Role(this, "MyWebAppECRRole", {
assumedBy: new ServicePrincipal("build.apprunner.amazonaws.com"),
});
role.addManagedPolicy({
managedPolicyArn:
"arn:aws:iam::aws:policy/service-role/AWSAppRunnerServicePolicyForECRAccess",
});
return role;
}
// 実行時のRoleを作成する。必要にあわせて定義する。
createTaskRole(): Role {
// AppRunner Task用のRoleを作成
let taskRole = new Role(this, "MyWebAppTaskRole", {
assumedBy: new ServicePrincipal("tasks.apprunner.amazonaws.com"),
});
// SSM の SecureString へのアクセス権
let googleJson = StringParameter.fromSecureStringParameterAttributes(
this,
"google-json",
{
parameterName: "/shared/google.json",
version: 1,
}
);
// Grant する
googleJson.grantRead(taskRole);
return taskRole;
}
}