Deploy a Secure Containerized App on Amazon ECS Fargate Using ECR and Secrets Manager
In this hands-on guide, you'll learn how to:
- ✅ Build and containerize a Python application
- ✅ Push Docker images to Amazon ECR
- ✅ Deploy containers on ECS Fargate
- ✅ Configure least-privilege IAM roles
- ✅ Inject secrets securely using AWS Secrets Manager
- ✅ Verify logs using CloudWatch
By the end, you'll have a production-style ECS deployment pipeline running entirely on AWS.
🚀 Architecture Overview
We'll use the following AWS services:
- Amazon ECR → Store container images
- Amazon ECS Fargate → Run serverless containers
- AWS IAM → Secure task permissions
- AWS Secrets Manager → Store secrets securely
- Amazon CloudWatch Logs → Monitor container logs
Step 1 — Clone the Application Repository
Open AWS CloudShell from the AWS Console and clone the repository:
git clone https://github.com/pluralsight-cloud/Lab-Secure-Container-Deployment-on-ECS-Fargate.git
cd Lab-Secure-Container-Deployment-on-ECS-Fargate
Inspect the application files:
cat app.py
cat Dockerfile
Step 2 — Authenticate Docker to Amazon ECR
Set your AWS account variables:
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
REGION=us-east-1
Authenticate Docker with ECR:
aws ecr get-login-password --region $REGION | docker login \
--username AWS \
--password-stdin \
$ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com
You should see:
Login Succeeded
Step 3 — Build and Push the Docker Image
Build the image:
docker build -t secure-fargate-app .
If you're using Apple Silicon (M1/M2/M3), use:
docker build --platform linux/amd64 -t secure-fargate-app .
Tag the image:
docker tag secure-fargate-app:latest \
$ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/secure-fargate-app:latest
Push the image:
docker push \
$ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/secure-fargate-app:latest
Step 4 — Verify the Image in Amazon ECR
Navigate to:
Amazon ECR → Repositories → secure-fargate-app
Step 5 — Create the ECS Task Execution Role
Go to:
IAM → Roles → Create Role
Choose:
- Trusted entity: AWS Service
- Use case: Elastic Container Service Task
Attach the policy:
AmazonECSTaskExecutionRolePolicy
Role name:
ecsTaskExecutionRole
Step 6 — Allow ECS to Read Secrets Manager
Add an inline policy to the execution role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "*"
}
]
}
Policy name:
SecretsManagerReadAccess
In production, always scope permissions to specific secret ARNs.
Step 7 — Create the ECS Task Role
Create another IAM role:
ecsTaskRole
This role intentionally has no permissions because the application does not call AWS services directly.
This is a great example of the principle of least privilege.
Step 8 — Create the ECS Task Definition
Go to:
Amazon ECS → Task Definitions → Create with JSON
Paste the following JSON:
{
"family": "secure-fargate-app",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"executionRoleArn": "arn:aws:iam::ACCOUNT_ID:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::ACCOUNT_ID:role/ecsTaskRole",
"containerDefinitions": [
{
"name": "secure-fargate-app",
"image": "ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/secure-fargate-app:latest",
"essential": true,
"secrets": [
{
"name": "DB_CREDENTIALS",
"valueFrom": "arn:aws:secretsmanager:us-east-1:ACCOUNT_ID:secret:prod/db-credentials"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/secure-fargate-app",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
}
}
}
]
}
Replace:
ACCOUNT_ID
with your actual AWS account ID.
🔐 Why Secrets Manager Matters
Instead of hardcoding secrets inside:
- Docker images
- Environment files
- Git repositories
ECS securely injects secrets at runtime using:
"valueFrom": "arn:aws:secretsmanager:..."
This keeps credentials out of source control and container layers.
Step 9 — Deploy the ECS Fargate Service
Go to:
Amazon ECS → Clusters → lab-cluster → Services → Create
Use the following settings:
| Setting | Value |
|---|---|
| Launch Type | Fargate |
| Task Definition | secure-fargate-app |
| Service Name | secure-fargate-svc |
| Platform Version | LATEST |
Networking
| Setting | Value |
|---|---|
| VPC | lab-vpc |
| Subnets | lab-public-subnet-1, lab-public-subnet-2 |
| Public IP | Enabled |
Create a security group:
fargate-sg
Inbound rule:
HTTP → Anywhere
For demo purposes only. Restrict inbound traffic properly in production environments.
Step 10 — Verify the Running Task
Open:
ECS → Clusters → lab-cluster → Services
If the task stops unexpectedly:
- Verify IAM role ARNs
- Check the ECR image URI
- Ensure Secrets Manager permissions exist
Step 11 — Validate Secret Injection in CloudWatch
Navigate to:
CloudWatch → Logs → Log Groups → /ecs/secure-fargate-app
Open the latest log stream.
You should see:
[OK] Secret successfully injected via Secrets Manager!
This confirms:
- ✅ ECS resolved the secret
- ✅ Secrets Manager integration works
- ✅ The container received the environment variable securely
🎯 What You Learned
In this project, you successfully:
- Built a Docker image
- Stored it in Amazon ECR
- Deployed it to ECS Fargate
- Applied least-privilege IAM roles
- Injected secrets securely
- Verified runtime logs in CloudWatch
This workflow reflects real-world AWS container deployment patterns used in production environments.
https://www.pluralsight.com/labs/aws/secure-container-deployment-on-ecs-fargate
https://github.com/pluralsight-cloud/Lab-Secure-Container-Deployment-on-ECS-Fargate








Top comments (0)