Deploying to AWS EC2
Virtual servers on AWS with full OS control, deploy via user data, Elastic Beanstalk, or SSH.
PlatformsAdvanced
Why
EC2 gives full control over the OS and runtime — install any software, run any process, attach any storage. It's the most flexible AWS compute, suitable for legacy apps and custom stacks.
Platform-as-a-Service adoption grew 24% in 2024 as teams shift from VM management to git-push deploys. the cloud infrastructure market reached $330B in 2024, growing 22% year-over-year (Synergy Research), and PaaS layers capture the majority of new workloads.
When
Use EC2 for legacy apps, custom software stacks, and workloads needing full OS access. Prefer Fargate/Lambda for containerized/serverless apps.
How
1. Launch — AMI (Amazon Linux 2023 or Ubuntu), instance type, key pair
2. User data — shell script runs on first boot to install app
3. Security group — open only needed ports (80, 443, 22)
4. Elastic IP — static IP for production
5. Load balancer — ALB for HTTPS, health checks, multi-AZ
6. Auto Scaling — ASG to scale instances on demand
7. Deploy — CodeDeploy, SSH+git pull, or Docker on EC2
Example
# user-data.sh — runs on first boot
#!/bin/bash
yum update -y
yum install -y docker
systemctl start docker
docker run -d -p 80:3000 myapp:latest
# Launch via AWS CLI
aws ec2 run-instances --image-id ami-012345 --instance-type t3.medium --user-data file://user-data.sh --security-group-ids sg-abc123
# ALB + ASG for production
aws elbv2 create-load-balancer --name myapp-alb --subnets subnet-1 subnet-2
Common Problems
- ⚠Security group too open — 0.0.0.0/0 on all ports, restrict to needed ports only
- ⚠No auto-recovery — instance dies, no ASG, manual restart needed
- ⚠Configuration drift between environments — use infrastructure-as-code (Terraform/Pulumi) to keep dev/staging/prod identical
Best Practices
- ✓Use Amazon Linux 2023 AMI — optimized for EC2, free, and AWS-supported
- ✓Always use ASG + ALB — auto-heals failed instances and distributes across AZs
- ✓Set up health checks and graceful shutdown — handle SIGTERM to drain in-flight requests before exit