Deploy a containerized machine learning model to AWS utilizing S3, ECR, and ECS for scalable, robust production service.
When moving from local Docker containers to production-grade deployments, the cloud provides the necessary scalability, reliability, and security. We'll explore how to host our model artifacts securely, manage Docker images with managed registries, and orchestrate containers across virtual instances using Amazon Web Services (AWS).
| # | Topic | Skill |
|---|---|---|
| 1 | IAM & Least Privilege | Configure deployment identities securely |
| 2 | Remote Artifacts (S3) | Store and version large ML models with DVC |
| 3 | Docker Optimization (ECR) | Build secure images utilizing build secrets |
| 4 | Container Orchestration (ECS) | Manage scalable compute clusters via EC2 |
| 5 | Resource Management | Teardown architecture and cost control |
| Service | Purpose in ML Deployment |
|---|---|
| IAM | Identity & Access Management for least privilege configuration. |
| S3 | Remote storage for large DVC artifacts (models, datasets). |
| ECR | Elastic Container Registry for hosting Docker images securely. |
| ECS | Elastic Container Service for orchestrating container deployments. |
| EC2 | Elastic Compute Cloud instances to provide compute for ECS clusters. |
Why This Matters: Using an AWS root account for routine deployment tasks is a significant security risk. We follow the principle of least privilege by creating a dedicated IAM user with only the necessary permissions.
ml-deployer-account).AmazonS3FullAccess, AmazonEC2ContainerRegistryFullAccess, AmazonECS_FullAccess.iam:PassRole for generating ECS instances, ec2:RunInstances, and CloudWatch log management.aws CLI using aws configure.Why This Matters:
Large binaries, such as serialized models (.pkl) and parquet data lakes, shouldn't be tracked in Git. We utilize DVC (Data Version Control) paired with an S3 bucket configured for versioning to protect against overwrites.
# Create an S3 Bucket securely via CLI
BUCKET_NAME="ml-artifact-store-unique-123"
aws s3 mb s3://${BUCKET_NAME} --region us-east-1
# Enable Versioning for safety
aws s3api put-bucket-versioning --bucket ${BUCKET_NAME} --versioning-configuration Status=Enabled
# Configure DVC to push to S3
dvc remote add -d s3remote s3://${BUCKET_NAME}/dvc-store
dvc push
Why This Matters: Instead of packaging gigantic model artifacts into a Docker repository directly, we pull them during the build pipeline using secure mount patterns. We then push the Docker image to ECR for managed hosting.
Never bake AWS credentials into Docker images. Use Docker Buildkit's --mount=type=secret.
# Inside the Dockerfile
RUN --mount=type=secret,id=aws,target=${HOME}/.aws/credentials,uid=1001,gid=1001 \
dvc pull /app/artifacts/models/processor.pkl /app/artifacts/models/model.pkl -v
Create the resilient repository:
aws ecr create-repository \
--repository-name ml-container-repo \
--image-scanning-configuration scanOnPush=true \
--image-tag-mutability IMMUTABLE # Prevents accidental tag overwrites in production
Authenticate and push using the BuildKit secret logic:
# Authenticate Docker to ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com
# Build securely mounting your local IAM credentials
docker buildx build --secret id=aws,src=$HOME/.aws/credentials --platform linux/amd64 -t ml-container-repo:v1 .
# Tag & Push
docker tag ml-container-repo:v1 $AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/ml-container-repo:v1
docker push $AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/ml-container-repo:v1
Why This Matters: Running a container manually doesn't scale. ECS coordinates clusters of resources, determining where, when, and how to run tasks reliably.
ml-cluster).ecsInstanceRole allowing EC2 instances to speak to ECS. Establish ecsTaskExecutionRole allowing tasks to pull ECR images & write logs.user-data.sh to configure the ECS agent:#!/bin/bash
mkdir -p /etc/ecs
echo ECS_CLUSTER='ml-cluster' >> /etc/ecs/ecs.config
Launch the instance using an ECS-Optimized AMI.
A Task Definition dictates how the container runs (memory, CPU, network mode, and roles).
{
"family": "ml-api-task",
"requiresCompatibilities": ["EC2"],
"networkMode": "bridge",
"executionRoleArn": "...",
"containerDefinitions": [
{
"name": "ml-api",
"image": "YOUR_ECR_IMAGE_URI",
"memoryReservation": 512,
"portMappings": [{"containerPort": 8000, "hostPort": 8000, "protocol": "tcp"}],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/ml-api-logs",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
}
}
}
]
}
Register the task definition, then create a Service specifying a desired task count to ensure high availability.
To avoid surprise billing, systematically tear down cloud artifacts. Reverse order is essential due to dependencies:
Key Takeaways:
# Create an S3 Bucket dynamically
aws s3 mb s3://my-ml-artifacts-bucket --region us-east-1
# Enable protection versioning
aws s3api put-bucket-versioning --bucket my-ml-artifacts-bucket --versioning-configuration Status=Enabled
# Docker Auth to ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com
Test your understanding with step-by-step solutions
5 questions · 90s per question
Each question has a 90-second time limit. Unanswered questions will be auto-submitted when time runs out.