Deploy Image on ECR to AWS App Runner with AWS CDK V2
Page content
AWS App Runner makes it easy to deploy a Web Server as long as it is a Docker container.
What’s more,
- Automatic redeployment of the ECR image when it is updated (or not automatic, of course).
- AutoScale and custom domains can also be configured.
- You can view metrics such as number of accesses, latency, number of instances, etc. without any configuration.
- Application logs can also be viewed automatically.
It’s all there. It will be very useful when you want to deploy a small web service.
Once you get used to it, it’s not that much trouble to set it up manually. However, since it is likely to be used many times in the future, I will summarize how to write with AWS CDK V2.
Version
node
:16.13.1
aws-cdk
:2.8.0 (build 8a5eb49)
tsc
:4.5.4
How To Write with AWS CDK v2
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";
// Image URI to deploy
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, // Role when accessing ECR?
},
imageRepository: {
imageIdentifier: IMAGE_URI,
imageRepositoryType: "ECR",
imageConfiguration: {
port: "8080", // Listen Port
runtimeEnvironmentVariables: [
// Runtime Environment Variables
{ name: "PRODUCTION", value: "1" },
],
startCommand: "web", // Commands when launching container execution
},
},
autoDeploymentsEnabled: true, // AutoDeploy when images pushed to ECR
},
instanceConfiguration: {
cpu: "1 vCPU",
memory: "2 GB",
instanceRoleArn: taskRole.roleArn,
},
});
}
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;
}
// Create a runtime Role. Define as needed.
createTaskRole(): Role {
// Create Role for AppRunner Task
let taskRole = new Role(this, "MyWebAppTaskRole", {
assumedBy: new ServicePrincipal("tasks.apprunner.amazonaws.com"),
});
// SSM's access rights to SecureString
let googleJson = StringParameter.fromSecureStringParameterAttributes(
this,
"google-json",
{
parameterName: "/shared/google.json",
version: 1,
}
);
// Grant
googleJson.grantRead(taskRole);
return taskRole;
}
}