OpenMCF logoOpenMCF

Loading...

AWS App Runner Service

Deploys an AWS App Runner Service from a container image or GitHub repository with automatic HTTPS, concurrency-based auto scaling, optional VPC egress via an inline VPC Connector, and optional customer-managed KMS encryption. The component supports two mutually exclusive source types: ECR image or GitHub code repository.

What Gets Created

When you deploy an AwsAppRunnerService resource, OpenMCF provisions:

  • App Runner Service — an aws:apprunner:Service resource with source configuration (image or code), instance sizing, health checks, networking, encryption, and observability settings
  • VPC Connector — created only when subnetIds are provided and no existing vpcConnectorArn is referenced, allowing the service to reach resources in your VPC (databases, caches, internal APIs)
  • Auto Scaling Configuration Version — created only when the autoScaling block is provided, controlling min/max instance counts and per-instance concurrency limits

Prerequisites

  • AWS credentials configured via environment variables or OpenMCF provider config
  • A container image in ECR or ECR Public if using image-based deployment
  • An IAM access role with ECR pull permissions if using a private ECR image (image_repository_type: ECR)
  • An App Runner Connection (created via AWS Console or CLI with GitHub OAuth) if using code-based deployment
  • VPC subnets and security groups if the service needs to access VPC resources
  • A customer-managed KMS key ARN if encrypting the service with your own key (note: changing this value requires replacing the service)

Quick Start

Create a file app-runner.yaml:

apiVersion: aws.openmcf.org/v1
kind: AwsAppRunnerService
metadata:
  name: my-api
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: dev.AwsAppRunnerService.my-api
spec:
  region: us-east-1
  imageSource:
    imageIdentifier: public.ecr.aws/nginx/nginx:latest
    imageRepositoryType: ECR_PUBLIC

Deploy:

openmcf apply -f app-runner.yaml

This creates a publicly accessible App Runner service running an ECR Public image with default settings: 1 vCPU, 2 GB memory, port 8080, and auto scaling from 1 to 25 instances.

Configuration Reference

Required Fields

FieldTypeDescriptionValidation
regionstringAWS region where the App Runner service will be created (e.g., us-east-1, eu-west-1).Required; non-empty
imageSource or codeSourceobjectDeployment source. Exactly one must be provided.CEL: exactly_one_source
imageSource.imageIdentifierstringFull container image URI including tag or digest (e.g., ACCOUNT.dkr.ecr.REGION.amazonaws.com/REPO:TAG).Min length 1
imageSource.imageRepositoryTypestringType of image repository: ECR (private) or ECR_PUBLIC.Must be ECR or ECR_PUBLIC
imageSource.accessRoleArnstringIAM role ARN that grants App Runner permission to pull from private ECR. Required when imageRepositoryType is ECR. Can reference AwsIamRole via valueFrom.Required for ECR
codeSource.repositoryUrlstringGitHub repository URL (e.g., https://github.com/owner/repo).Min length 1
codeSource.branchstringBranch name to deploy from (e.g., main).Min length 1
codeSource.connectionArnstringARN of an App Runner Connection for GitHub access.Required
codeSource.configurationSourcestringWhere build/runtime config comes from: API (inline in spec) or REPOSITORY (apprunner.yaml in repo).Must be API or REPOSITORY

Optional Fields

FieldTypeDefaultDescription
portstring8080Port the application listens on. App Runner routes incoming HTTPS traffic to this port.
startCommandstring—Override the container start command. For image source, overrides ENTRYPOINT/CMD.
environmentVariablesmap<string, string>{}Plaintext environment variables injected at runtime. Keys prefixed with AWSAPPRUNNER are reserved.
environmentSecretsmap<string, string>{}Environment secrets as ARNs of Secrets Manager secrets or SSM Parameter Store parameters. The instanceRoleArn must have read permissions.
cpustring1024CPU per instance. Accepts 256, 512, 1024, 2048, 4096 or 0.25 vCPU, 0.5 vCPU, 1 vCPU, 2 vCPU, 4 vCPU.
memorystring2048Memory per instance. Accepts 512–12288 (MB) or 0.5 GB–12 GB. Not all CPU/memory combinations are valid.
instanceRoleArnstring—IAM role instances assume at runtime to call AWS APIs (S3, DynamoDB, etc.). Can reference AwsIamRole via valueFrom.
healthCheck.protocolstringTCPHealth check protocol: TCP (port open) or HTTP (GET request expecting 200).
healthCheck.pathstring/URL path for HTTP health checks. Ignored when protocol is TCP.
healthCheck.intervalSecondsint5Seconds between health checks. Range: 1–20.
healthCheck.timeoutSecondsint2Seconds to wait for a health check response. Range: 1–20.
healthCheck.healthyThresholdint1Consecutive successes to mark healthy. Range: 1–20.
healthCheck.unhealthyThresholdint5Consecutive failures to mark unhealthy and trigger replacement. Range: 1–20.
autoScaling.minSizeint1Minimum warm instances kept running at all times. Range: 1–25.
autoScaling.maxSizeint25Maximum instances during traffic spikes. Range: 1–25. Must be >= minSize.
autoScaling.maxConcurrencyint100Concurrent requests per instance before scaling out. Range: 1–200.
vpcConnectorArnstring—ARN of an existing VPC Connector. Mutually exclusive with subnetIds.
subnetIdsstring[][]VPC subnet IDs for creating an inline VPC Connector. Mutually exclusive with vpcConnectorArn. Can reference AwsVpc via valueFrom.
securityGroupIdsstring[][]Security group IDs for the inline VPC Connector. Only used when subnetIds is provided. Can reference AwsSecurityGroup via valueFrom.
isPubliclyAccessiblebooltrueWhen false, the service is only reachable via a VPC Ingress Connection (not managed by this component).
ipAddressTypestringIPV4IP address type for the endpoint: IPV4 or DUAL_STACK (IPv4 + IPv6).
kmsKeyArnstring—Customer-managed KMS key ARN for encrypting the service's image and data logs. ForceNew: changing this replaces the service. Can reference AwsKmsKey via valueFrom.
observabilityEnabledboolfalseEnables AWS X-Ray tracing. Requires observabilityConfigurationArn.
observabilityConfigurationArnstring—ARN of an App Runner Observability Configuration. Required when observabilityEnabled is true.
autoDeploymentsEnabledbooltrueAutomatically redeploy when the source image tag is pushed or the code branch receives a commit.
codeSource.runtimestring—Runtime for code builds. Required when configurationSource is API. Values: PYTHON_3, NODEJS_12–NODEJS_18, CORRETTO_8, CORRETTO_11, GO_1, DOTNET_6, PHP_81, RUBY_31.
codeSource.buildCommandstring—Shell command to build the application (e.g., npm ci && npm run build). Only used when configurationSource is API.
codeSource.sourceDirectorystring—Subdirectory containing the application source. Defaults to repository root. Useful for monorepos.

Examples

Image from ECR Public with Custom Port

Deploy a public container image with a non-default port and reduced instance size:

apiVersion: aws.openmcf.org/v1
kind: AwsAppRunnerService
metadata:
  name: lightweight-api
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: dev.AwsAppRunnerService.lightweight-api
spec:
  imageSource:
    imageIdentifier: public.ecr.aws/myalias/my-app:latest
    imageRepositoryType: ECR_PUBLIC
  port: "3000"
  cpu: "512"
  memory: "1024"

Private ECR Image with VPC Access

Deploy from a private ECR registry with VPC egress so the service can reach an RDS database:

apiVersion: aws.openmcf.org/v1
kind: AwsAppRunnerService
metadata:
  name: backend-api
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: staging.AwsAppRunnerService.backend-api
spec:
  region: us-east-1
  imageSource:
    imageIdentifier: 123456789012.dkr.ecr.us-east-1.amazonaws.com/backend:v1.2.0
    imageRepositoryType: ECR
    accessRoleArn: arn:aws:iam::123456789012:role/apprunner-ecr-access
  port: "8080"
  cpu: "1024"
  memory: "2048"
  instanceRoleArn: arn:aws:iam::123456789012:role/backend-instance-role
  environmentVariables:
    DB_HOST: mydb.cluster-abc123.us-east-1.rds.amazonaws.com
    DB_PORT: "5432"
  environmentSecrets:
    DB_PASSWORD: arn:aws:secretsmanager:us-east-1:123456789012:secret:backend/db-password
  subnetIds:
    - subnet-private-az1
    - subnet-private-az2
  securityGroupIds:
    - sg-backend-egress
  healthCheck:
    protocol: HTTP
    path: /health
    intervalSeconds: 10
    timeoutSeconds: 5
    healthyThreshold: 1
    unhealthyThreshold: 3

GitHub Code Source

Deploy directly from a GitHub repository using a managed Node.js runtime:

apiVersion: aws.openmcf.org/v1
kind: AwsAppRunnerService
metadata:
  name: web-frontend
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: prod.AwsAppRunnerService.web-frontend
spec:
  region: us-east-1
  codeSource:
    repositoryUrl: https://github.com/my-org/web-frontend
    branch: main
    connectionArn: arn:aws:apprunner:us-east-1:123456789012:connection/github-conn/abc123
    configurationSource: API
    runtime: NODEJS_18
    buildCommand: npm ci && npm run build
  port: "3000"
  startCommand: npm start
  cpu: "1024"
  memory: "2048"
  autoScaling:
    minSize: 2
    maxSize: 10
    maxConcurrency: 80

Full-Featured Production Deployment

Production configuration with private ECR, VPC networking, KMS encryption, X-Ray observability, tuned auto scaling, and controlled deployments:

apiVersion: aws.openmcf.org/v1
kind: AwsAppRunnerService
metadata:
  name: prod-api
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: prod.AwsAppRunnerService.prod-api
spec:
  region: us-east-1
  imageSource:
    imageIdentifier: 123456789012.dkr.ecr.us-east-1.amazonaws.com/prod-api:v3.1.0
    imageRepositoryType: ECR
    accessRoleArn: arn:aws:iam::123456789012:role/apprunner-ecr-access
  port: "8080"
  cpu: "2048"
  memory: "4096"
  instanceRoleArn: arn:aws:iam::123456789012:role/prod-api-instance-role
  environmentVariables:
    LOG_LEVEL: info
    SERVICE_NAME: prod-api
  environmentSecrets:
    DATABASE_URL: arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/database-url
    API_KEY: arn:aws:ssm:us-east-1:123456789012:parameter/prod/api-key
  subnetIds:
    - subnet-private-az1
    - subnet-private-az2
    - subnet-private-az3
  securityGroupIds:
    - sg-prod-api-egress
  healthCheck:
    protocol: HTTP
    path: /readyz
    intervalSeconds: 5
    timeoutSeconds: 2
    healthyThreshold: 1
    unhealthyThreshold: 3
  autoScaling:
    minSize: 3
    maxSize: 20
    maxConcurrency: 50
  kmsKeyArn: arn:aws:kms:us-east-1:123456789012:key/mrk-prod-encryption-key
  observabilityEnabled: true
  observabilityConfigurationArn: arn:aws:apprunner:us-east-1:123456789012:observabilityconfiguration/xray-config/1/abc123
  autoDeploymentsEnabled: false
  isPubliclyAccessible: true
  ipAddressType: DUAL_STACK

Using Foreign Key References

Reference other OpenMCF-managed resources instead of hardcoding IDs:

apiVersion: aws.openmcf.org/v1
kind: AwsAppRunnerService
metadata:
  name: ref-api
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: prod.AwsAppRunnerService.ref-api
spec:
  region: us-east-1
  imageSource:
    imageIdentifier: 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-api:latest
    imageRepositoryType: ECR
    accessRoleArn:
      valueFrom:
        kind: AwsIamRole
        name: ecr-access-role
        field: status.outputs.role_arn
  instanceRoleArn:
    valueFrom:
      kind: AwsIamRole
      name: api-instance-role
      field: status.outputs.role_arn
  subnetIds:
    - valueFrom:
        kind: AwsVpc
        name: my-vpc
        field: status.outputs.private_subnets[0].id
    - valueFrom:
        kind: AwsVpc
        name: my-vpc
        field: status.outputs.private_subnets[1].id
  securityGroupIds:
    - valueFrom:
        kind: AwsSecurityGroup
        name: api-egress-sg
        field: status.outputs.security_group_id
  kmsKeyArn:
    valueFrom:
      kind: AwsKmsKey
      name: service-encryption-key
      field: status.outputs.key_arn

Stack Outputs

After deployment, the following outputs are available in status.outputs:

OutputTypeDescription
service_arnstringFull ARN of the App Runner Service
service_idstringUnique identifier assigned by App Runner
service_urlstringPublic HTTPS URL for the service (e.g., abc123.us-east-1.awsapprunner.com)
service_namestringComputed name of the service (derived from metadata.name)
service_statusstringCurrent operational status (e.g., RUNNING, CREATE_FAILED, OPERATION_IN_PROGRESS)
vpc_connector_arnstringARN of the VPC Connector. Only set when VPC egress is configured via subnetIds.
auto_scaling_configuration_arnstringARN of the Auto Scaling Configuration Version. Only set when autoScaling is provided.

Related Components

  • AwsVpc — provides subnets for VPC Connector egress
  • AwsSecurityGroup — controls outbound traffic from the VPC Connector
  • AwsIamRole — provides the ECR access role and instance runtime role
  • AwsKmsKey — provides the customer-managed encryption key
  • AwsEcrRepo — hosts private container images for image-based deployments

Next article

AWS Athena Workgroup

AWS Athena Workgroup Deploys an Amazon Athena workgroup with configurable query result storage, server-side encryption, per-query cost controls, and optional Apache Spark execution support. The workgroup enforces governance settings so individual queries cannot override result locations or encryption policies. What Gets Created When you deploy an AwsAthenaWorkgroup resource, OpenMCF provisions: Athena Workgroup — an awsathenaworkgroup resource with the specified name, configuration enforcement,...
Read next article
Presets
3 ready-to-deploy configurationsView presets →