graph TB
Internet["π Internet<br/>User/Client"]
subgraph Region["<b>Region: eu-central-1</b>"]
subgraph VPC_BOX["<b>VPC: 10.0.0.0/16</b><br/>(spans multiple AZs)"]
IGW["<b>Internet Gateway</b><br/>igw-xxx"]
RouteTable["<b>Route Table</b><br/>0.0.0.0/0 β Subnet"]
subgraph AZ_1a["<b>AZ: eu-central-1a</b>"]
Subnet["<b>Public Subnet</b><br/>10.0.1.0/24"]
SG["<b>Security Group</b><br/>nginx-sg"]
SG_Rule["<b>Inbound</b><br/>TCP/80 from 0.0.0.0/0"]
ENI["<b>Elastic Network Interface</b><br/>Public IP 3.125.45.67"]
Service["<b>ECS Service</b><br/>my-service"]
TaskDef["<b>Task Definition</b><br/>my-server-family:1"]
Fargate["<b>AWS Fargate</b><br/>Serverless Compute"]
Container["<b>nginx:latest</b><br/>Port 80"]
end
AZ_1b["<b>AZ: eu-central-1b</b><br/>(additional subnets possible)"]
AZ_1c["<b>AZ: eu-central-1c</b><br/>(additional subnets possible)"]
end
end
Internet -->|HTTP/80| IGW
IGW -->|Routes via| RouteTable
RouteTable -->|Directs to| Subnet
Subnet -->|Contains| SG
SG_Rule -.->|Rule| SG
SG -->|Allows| ENI
Service -->|Orchestrates| TaskDef
TaskDef -->|Deploys to| Fargate
Fargate -->|Runs| Container
Container -->|Binds to| ENI
ENI -.->|Response| Internet
style Internet fill:#FFF4E6,stroke:#FF9800,stroke-width:3px
style Region fill:#FAFAFA,stroke:#424242,stroke-width:3px
style VPC_BOX fill:#E3F2FD,stroke:#1976D2,stroke-width:3px
style AZ_1a fill:#F5F5F5,stroke:#616161,stroke-width:2px,stroke-dasharray: 5 5
style AZ_1b fill:#F5F5F5,stroke:#616161,stroke-width:2px,stroke-dasharray: 5 5
style AZ_1c fill:#F5F5F5,stroke:#616161,stroke-width:2px,stroke-dasharray: 5 5
style IGW fill:#C8E6C9,stroke:#388E3C,stroke-width:2px
style RouteTable fill:#E8F5E9,stroke:#558B2F,stroke-width:2px
style Subnet fill:#E1F5FE,stroke:#0097A7,stroke-width:2px
style SG fill:#FCE4EC,stroke:#C2185B,stroke-width:2px
style SG_Rule fill:#F8BBD0,stroke:#C2185B,stroke-width:1px
style ENI fill:#FFF9C4,stroke:#F57F17,stroke-width:2px
style Service fill:#F1F8E9,stroke:#689F38,stroke-width:2px
style TaskDef fill:#F1F8E9,stroke:#689F38,stroke-width:2px
style Fargate fill:#E0F2F1,stroke:#00897B,stroke-width:2px
style Container fill:#C8E6C9,stroke:#388E3C,stroke-width:3px
| Component | Description | AWS Service | Tier |
|---|---|---|---|
| Internet Gateway | Connection between VPC and Internet | EC2 | Edge |
| VPC | Isolated Network (10.0.0.0/16) | EC2 | Network |
| Public Subnet | Network segment with IGW access (10.0.1.0/24) | EC2 | Network |
| Security Group | Stateful Firewall (L4) - Port 80 allow | EC2 | Network |
| Elastic Network Interface | Virtual Network Card with Public IP | EC2 | Network |
| ECS Cluster | Container Orchestration Control Plane | ECS | Orchestration |
| ECS Service | Managed Container Lifecycle Manager (desired: 1) | ECS | Orchestration |
| Task Definition | Container Configuration Template (CPU: 256, RAM: 512) | ECS | Orchestration |
| AWS Fargate | Serverless Container Runtime | ECS | Compute |
| Container | nginx:latest Docker Image | Fargate | Application |
aws configure
# AWS Access Key ID: [enter]
# AWS Secret Access Key: [enter]
# Default region: eu-central-1
# Output: json# Create VPC
VPC_ID=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16 --region eu-central-1 --query 'Vpc.VpcId' --output text)
# Create Subnet + enable public IPs
SUBNET_ID=$(aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block 10.0.1.0/24 --availability-zone eu-central-1a --region eu-central-1 --query 'Subnet.SubnetId' --output text)
aws ec2 modify-subnet-attribute --subnet-id $SUBNET_ID --map-public-ip-on-launch --region eu-central-1
# Create Internet Gateway + attach
IGW_ID=$(aws ec2 create-internet-gateway --region eu-central-1 --query 'InternetGateway.InternetGatewayId' --output text)
aws ec2 attach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID --region eu-central-1
# Add route to IGW
ROUTE_TABLE_ID=$(aws ec2 describe-route-tables --filters "Name=vpc-id,Values=$VPC_ID" --query 'RouteTables[0].RouteTableId' --output text --region eu-central-1)
aws ec2 create-route --route-table-id $ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW_ID --region eu-central-1
# Create Security Group + allow HTTP
SG_ID=$(aws ec2 create-security-group --group-name nginx-sg --description "Allow HTTP" --vpc-id $VPC_ID --region eu-central-1 --query 'GroupId' --output text)
aws ec2 authorize-security-group-ingress --group-id $SG_ID --protocol tcp --port 80 --cidr 0.0.0.0/0 --region eu-central-1
# Verify
echo "VPC: $VPC_ID | Subnet: $SUBNET_ID | IGW: $IGW_ID | SG: $SG_ID"# Register Task Definition
aws ecs register-task-definition \
--family my-server-family --network-mode awsvpc --requires-compatibilities FARGATE \
--cpu 256 --memory 512 \
--container-definitions '[{"name":"my-server","image":"nginx:latest","portMappings":[{"containerPort":80,"hostPort":80,"protocol":"tcp"}]}]' \
--region eu-central-1
# Create Cluster
aws ecs create-cluster --cluster-name my-cluster --region eu-central-1
# Create Service
aws ecs create-service \
--cluster my-cluster --service-name my-service \
--task-definition my-server-family:1 --desired-count 1 --launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[$SUBNET_ID],securityGroups=[$SG_ID],assignPublicIp=ENABLED}" \
--region eu-central-1# Get task ARN
TASK_ARN=$(aws ecs list-tasks --cluster my-cluster --desired-status RUNNING --region eu-central-1 --query 'taskArns[0]' --output text)
# Get ENI + Public IP
ENI_ID=$(aws ecs describe-tasks --cluster my-cluster --tasks $TASK_ARN --region eu-central-1 --query 'tasks[0].attachments[0].details[?name==`networkInterfaceId`].value' --output text)
PUBLIC_IP=$(aws ec2 describe-network-interfaces --network-interface-ids $ENI_ID --region eu-central-1 --query 'NetworkInterfaces[0].Association.PublicIp' --output text)
# Test
curl http://$PUBLIC_IP
# Expected: HTTP 200 with NGINX welcome page# Delete in order
aws ecs delete-service --cluster my-cluster --service my-service --force --region eu-central-1
aws ecs delete-cluster --cluster my-cluster --region eu-central-1
aws ec2 detach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID --region eu-central-1
aws ec2 delete-internet-gateway --internet-gateway-id $IGW_ID --region eu-central-1
aws ec2 delete-security-group --group-id $SG_ID --region eu-central-1
aws ec2 delete-subnet --subnet-id $SUBNET_ID --region eu-central-1
aws ec2 delete-vpc --vpc-id $VPC_ID --region eu-central-1