AWS
AWS App Runner: Simplified Container and Source Code Deployment
Learn how to use AWS App Runner to deploy and run containerized web applications and APIs with automatic scaling and load balancing
March 15, 2024
DevHub Team
5 min read
AWS App Runner: Simplified Container and Source Code Deployment
AWS App Runner is a fully managed service that makes it easy to deploy containerized web applications and APIs at scale. This guide explores its features, use cases, and best practices.
Service Overview
graph TB
subgraph AppRunner["AWS App Runner"]
direction TB
Source["Source Code/Container"]
Build["Build Process"]
Deploy["Deployment"]
Run["Runtime"]
end
subgraph Features["Service Features"]
direction TB
AS["Auto Scaling"]
LB["Load Balancing"]
SSL["SSL/TLS"]
VPC["VPC Integration"]
end
Source --> Build
Build --> Deploy
Deploy --> Run
Run --> Features
classDef aws fill:#FF9900,stroke:#232F3E,color:#232F3E
class AppRunner,Features aws
Getting Started
1. Source Code Deployment
Example Node.js application:
// app.js const express = require('express'); const app = express(); const port = process.env.PORT || 3000; app.get('/', (req, res) => { res.json({ message: 'Hello from App Runner!' }); }); app.listen(port, () => { console.log(`Server running on port ${port}`); });
Configuration file:
# apprunner.yaml version: 1.0 runtime: nodejs12 build: commands: pre-build: - npm install build: - npm run build run: command: node app.js network: port: 3000
2. Container Deployment
Dockerfile example:
FROM node:14-alpine WORKDIR /app COPY package*.json ./ RUN npm install COPY . . EXPOSE 3000 CMD ["node", "app.js"]
Infrastructure as Code
AWS CDK Implementation
import * as apprunner from '@aws-cdk/aws-apprunner-alpha'; import * as ecr from 'aws-cdk-lib/aws-ecr'; // Create App Runner service from container const service = new apprunner.Service(this, 'Service', { source: apprunner.Source.fromEcr({ imageConfiguration: { port: 3000, }, repository: ecr.Repository.fromRepositoryName( this, 'Repo', 'my-app-repo' ), tag: 'latest', }), });
CloudFormation Template
Resources: AppRunnerService: Type: AWS::AppRunner::Service Properties: ServiceName: my-web-app SourceConfiguration: AuthenticationConfiguration: AccessRoleArn: !GetAtt AppRunnerECRAccessRole.Arn ImageRepository: ImageIdentifier: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/my-app:latest ImageConfiguration: Port: 3000 InstanceConfiguration: Cpu: 1024 Memory: 2048
Auto Scaling Configuration
{ "AutoScalingConfigurationName": "production-config", "MaxConcurrency": 100, "MinSize": 1, "MaxSize": 25, "Tags": [ { "Key": "Environment", "Value": "Production" } ] }
Networking and Security
VPC Configuration
Resources: AppRunnerVpcConnector: Type: AWS::AppRunner::VpcConnector Properties: VpcConnectorName: my-vpc-connector Subnets: - subnet-123456 - subnet-789012 SecurityGroups: - sg-123456
IAM Configuration
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage" ], "Resource": "*" } ] }
Monitoring and Logging
CloudWatch Integration
import boto3 import datetime cloudwatch = boto3.client('cloudwatch') def get_app_metrics(): response = cloudwatch.get_metric_statistics( Namespace='AWS/AppRunner', MetricName='RequestCount', Dimensions=[ { 'Name': 'ServiceName', 'Value': 'my-web-app' } ], StartTime=datetime.datetime.utcnow() - datetime.timedelta(hours=1), EndTime=datetime.datetime.utcnow(), Period=60, Statistics=['Sum'] ) return response
Custom Metrics
const AWS = require('aws-sdk'); const cloudwatch = new AWS.CloudWatch(); async function publishCustomMetric(value) { await cloudwatch.putMetricData({ Namespace: 'MyAppMetrics', MetricData: [{ MetricName: 'BusinessTransactions', Value: value, Unit: 'Count', Dimensions: [{ Name: 'ServiceName', Value: 'my-web-app' }] }] }).promise(); }
CI/CD Integration
GitHub Actions Workflow
name: Deploy to App Runner on: push: branches: [ main ] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-west-2 - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v1 - name: Build and push image env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} ECR_REPOSITORY: my-app IMAGE_TAG: latest run: | docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG - name: Deploy to App Runner run: | aws apprunner update-service \ --service-arn ${{ secrets.APPRUNNER_SERVICE_ARN }} \ --source-configuration imageRepository={imageIdentifier=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG}
Performance Optimization
1. Resource Configuration
# Optimal resource configuration Resources: AppRunnerService: Type: AWS::AppRunner::Service Properties: InstanceConfiguration: Cpu: 1 vCPU Memory: 2 GB AutoScalingConfigurationArn: !Ref AutoScalingConfig HealthCheckConfiguration: Path: /health Protocol: TCP Interval: 10 Timeout: 5 HealthyThreshold: 2 UnhealthyThreshold: 3
2. Caching Strategy
const express = require('express'); const app = express(); const cache = require('memory-cache'); app.get('/api/data', (req, res) => { const key = req.url; const cachedResponse = cache.get(key); if (cachedResponse) { return res.json(cachedResponse); } // Generate response const response = generateResponse(); cache.put(key, response, 300000); // Cache for 5 minutes res.json(response); });
Cost Optimization
1. Auto Scaling Configuration
{ "AutoScalingConfigurationName": "cost-optimized", "MaxConcurrency": 50, "MinSize": 1, "MaxSize": 10, "Tags": [ { "Key": "CostCenter", "Value": "WebApp" } ] }
2. Resource Utilization
# Resource optimization example Resources: OptimizedService: Type: AWS::AppRunner::Service Properties: InstanceConfiguration: Cpu: "1024" # 1 vCPU Memory: "2048" # 2 GB AutoScalingConfigurationArn: !Ref CostOptimizedConfig ObservabilityConfiguration: ObservabilityEnabled: true TraceConfiguration: Vendor: AWSXRAY
Best Practices
1. Application Design
- Use health checks
- Implement graceful shutdown
- Handle environment variables
- Optimize container size
2. Operational Excellence
- Enable observability
- Implement proper logging
- Use infrastructure as code
- Regular monitoring and alerts
3. Security
- Use VPC connectivity
- Implement least privilege
- Enable encryption
- Regular security updates
Troubleshooting Guide
Common issues and solutions:
-
Deployment Failures
- Check build logs
- Verify source configuration
- Validate container image
- Check resource limits
-
Performance Issues
- Monitor metrics
- Check resource utilization
- Validate auto-scaling
- Review application logs
References
- AWS App Runner Documentation
- App Runner Best Practices
- Pricing Information
- App Runner Workshop
- Container Security
- Auto Scaling Guide
Related Posts
- AWS Lambda Container Support: A Comprehensive Guide - Explore serverless container deployments
- AWS ECS vs EKS in 2024: A Comprehensive Comparison - Compare container orchestration services
- AWS Graviton3: Next-Generation ARM-based Computing - Learn about ARM-based computing for containers
- Introduction to AWS Fargate: Serverless Container Orchestration - Discover serverless container orchestration
App Runner
Containers
Serverless
DevOps