DevOps.Academy
CoursesCurriculumPricing

    Loading…

    ↑ ↓ move · ↵ open · Ctrl K anywhere

    ◔My learningSign in
    DevOps.Academy

    Free, hands-on DevOps lessons. Made with care in India.

    Learn

    All coursesLinux roadmapCurriculumMy learning

    Academy

    PricingCertificates

    Legal

    PrivacyTermsContact

    devops.rajeev.pro

    AWS for DevOpsLesson 11 of 17
    Your progress · 0%
    On this page
    1. Three layers, three responsibilities
    2. ECR: the image boundary
    3. ECS task definitions
    4. Fargate task and service
    5. ECS or EKS?
    6. ECS capacity providers
    7. Task definitions: the runtime contract
    8. Service discovery and Service Connect
    9. Put a service behind an ALB
    10. Deployments and automatic rollback
    11. Scale, inspect and choose the platform
    ↖ Course roadmap
    Lesson 11 · Containers

    Containers on AWS: ECR, ECS and EKS

    Store an image in ECR, run a Fargate task on ECS, and choose EKS only when Kubernetes is a real requirement.

    30 min read · intermediate · hands-on

    By the end of this lesson you'll be able to

    0 of 4 complete

    Three layers, three responsibilities

    ECR stores OCI container images. ECS schedules containers as tasks. Fargate supplies the compute capacity for an ECS task without making you patch or scale EC2 hosts. These are separate responsibilities, so secure and observe each one separately.

    (1) ECS starts with a cluster boundary. A production cluster usually has services; this lesson runs one short task for inspection.© Screenshot: DevOps Academy

    (1) ECS starts with a cluster boundary. A production cluster usually has services; this lesson runs one short task for inspection.© Screenshot: DevOps Academy

    ECR: the image boundary

    Create one repository per image or per carefully chosen ownership boundary. Enable scan-on-push, use immutable tags for releases, and add a lifecycle policy so old digests do not accumulate forever. A tag is a pointer; a digest identifies the exact image.

    The task in this lesson used the public nginx image so the exercise did not need to build or push an image. In a real pipeline, authenticate to ECR, push a content-addressed image, and deploy the digest rather than trusting a mutable latest tag.

    ECS task definitions

    A task definition is versioned. It declares the image, CPU, memory, ports, logging, network mode and IAM roles. The execution role lets the ECS agent pull an image and write logs. The task role is different: it is the identity available to application code. Keep the two roles separate and grant each only what it needs.

    Fargate task and service

    A task is one running copy of a task definition. A service is the controller for a desired number of long-running tasks. The mission uses one task and no service, so it is easy to see the lifecycle and clean it up. For a web application, put a service behind a load balancer, use private subnets where possible, and allow inbound traffic only from the load balancer security group.

    A public IP is for this short exercise only

    The mission assigns a public IP so a task in a practice subnet can pull its public image. It exposes no application port to the internet. Production workloads should normally pull through private networking and keep tasks in private subnets with controlled egress.

    ECS or EKS?

    Choose ECS when AWS-native scheduling and a smaller operational surface fit the team. Choose EKS when Kubernetes compatibility, its ecosystem or an existing platform standard justifies the cluster lifecycle. EKS adds control-plane integration, node or Fargate capacity, IAM mappings, upgrades and more policy surface. Do not select it merely because the word “container” appears in the requirement.

    Production controls

    Pin image digests, scan and sign images, use task roles instead of keys, send logs to CloudWatch, set CPU and memory limits, define health checks, restrict security groups, encrypt secrets, and deploy through a service with a rollback strategy.

    ECS capacity providers

    Capacity providers answer a placement question: where should ECS put a task? FARGATE runs on AWS-managed capacity, FARGATE_SPOT trades interruption risk for a lower price, and EC2 places tasks on instances that your team patches and scales. Keep interruption-tolerant workers separate from stateful or latency-sensitive services.

    The cluster is active. It has two active services. Four tasks are running. The api and web services are listed.© Screenshot: DevOps Academy

    The cluster is active. It has two active services. Four tasks are running. The api and web services are listed.© Screenshot: DevOps Academy

    Task definitions: the runtime contract

    The task definition is the versioned contract between the scheduler and the container. awsvpc gives each task an elastic network interface and security group. CPU and memory are task-level limits. A port mapping gives the proxy or load balancer a named destination. A health check lets ECS replace a process that is alive but not serving.

    The execution role is used by the ECS agent to pull images and write logs. The task role is assumed by application code. They are intentionally different. In the practice definitions, the web task has the execution role and the api task also has academy-ecs-task-role for ECS Exec and application permissions.

    The execution role is visible. The network mode is awsvpc. The task uses 0.25 vCPU and 0.5 GiB. The container definition is web. The task memory graph shows the reservation.© Screenshot: DevOps Academy

    The execution role is visible. The network mode is awsvpc. The task uses 0.25 vCPU and 0.5 GiB. The container definition is web. The task memory graph shows the reservation.© Screenshot: DevOps Academy

    (1) The api task has an application task role. (2) The execution role is separate. (3) awsvpc supplies task networking. (4) CPU and memory are explicit. (5) The container is the api service.© Screenshot: DevOps Academy

    (1) The api task has an application task role. (2) The execution role is separate. (3) awsvpc supplies task networking. (4) CPU and memory are explicit. (5) The container is the api service.© Screenshot: DevOps Academy

    The logging choice matters too. awslogs sends each container stream to CloudWatch Logs. FireLens is useful when a central log router must enrich or route records to another destination. Secrets should come from Secrets Manager or SSM references, not from a baked image or plain environment variable.

    Service discovery and Service Connect

    Cloud Map gives services names inside a namespace. Service Connect builds on that registry with managed proxies, client aliases and consistent service-to-service telemetry. Use plain Cloud Map when clients can resolve and call the registered endpoint themselves. Use Service Connect when ECS services need a uniform, named mesh-like connection between tasks without building that proxy layer by hand.

    The web container calls http://api:80/; Service Connect maps that alias to the api service. This keeps the web task independent of task IP addresses.

    Put a service behind an ALB

    An ECS service keeps the desired number of tasks running. An ALB target group checks the task health and routes the request to a healthy ENI. The ALB security group should accept the listener port; the task security group should accept the container port only from the ALB security group.

    The live practice ALB returned real responses:

    $ curl http://academy-ecs-alb-981205580.ap-south-1.elb.amazonaws.com/
    web ok from ip-172-31-8-246.ap-south-1.compute.internal
    $ curl http://academy-ecs-alb-981205580.ap-south-1.elb.amazonaws.com/api/
    {"service":"api","version":"v1","host":"ip-172-31-13-164.ap-south-1.compute.internal"}
    
    curl http://academy-ecs-alb-981205580.ap-south-1.elb.amazonaws.com/
    • curlmake an HTTP request

    Deployments and automatic rollback

    Rolling deployment replaces tasks while respecting minimumHealthyPercent and maximumPercent. A deployment circuit breaker watches whether the new task set can become healthy. With rollback enabled, ECS returns to the last completed deployment when the new revision cannot start. Blue/green with CodeDeploy is a better fit when two task sets must coexist and traffic must shift in controlled steps; it adds a second target group and lifecycle hooks.

    The practice service was updated to an image tag that does not exist. ECS recorded a real pull failure:

    (service api) was unable to place a task. Reason: CannotPullContainerError: pull image manifest has been retried 7 time(s): failed to resolve ref public.ecr.aws/nginx/nginx:does-not-exist: not found.
    

    Scale, inspect and choose the platform

    Target tracking keeps a service metric near a target. The practice web service used ECS average CPU at 50 percent, with two to four tasks. Choose a target that protects latency and downstream capacity; scaling is not a substitute for backpressure.

    ECS Exec opens a shell through Systems Manager without exposing SSH. It needs the task role's ssmmessages actions, the Session Manager plugin and a task launched with execute-command enabled. App Runner is a simpler managed web deployment when you bring a source repository or image and do not need ECS's task and network controls. EKS is the right boundary when Kubernetes APIs and ecosystem compatibility are requirements; it is not a default for every container.

    The desired count is two and both tasks are running. The active task definition is shown. The health and deployment tabs are available for operations. The service reports completed tasks.© Screenshot: DevOps Academy

    The desired count is two and both tasks are running. The active task definition is shown. The health and deployment tabs are available for operations. The service reports completed tasks.© Screenshot: DevOps Academy

    The web service is the ALB-facing service. Its running task count is visible. Deployment controls are available. Health and events are separate operational views.© Screenshot: DevOps Academy

    The web service is the ALB-facing service. Its running task count is visible. Deployment controls are available. Health and events are separate operational views.© Screenshot: DevOps Academy
    ⌘
    Mini mission

    Run one disposable Fargate task

    Create an ECR repository, define a small nginx task, run it on Fargate, inspect its state, then delete every temporary resource. No image is pushed in this mission; the task pulls a public image.

    Input: AWS CLI credentials allowed to create and delete temporary ECR and ECS resourcesOutput: A RUNNING task followed by confirmed deletion of the task, cluster, repository and temporary execution role
    Reveal one safe solution
    $ export AWS_REGION=ap-south-1
    $ export REPO="academy-containers-$RANDOM"
    $ export CLUSTER="academy-fargate-$RANDOM"
    $ export FAMILY="academy-nginx-$RANDOM"
    $ export ROLE="academy-ecs-exec-$RANDOM"
    $ export VPC=$(aws ec2 describe-vpcs --filters Name=is-default,Values=true --query 'Vpcs[0].VpcId' --output text)
    $ export SUBNET=$(aws ec2 describe-subnets --filters Name=vpc-id,Values="$VPC" --query 'Subnets[?DefaultForAz==`true`].SubnetId | [0]' --output text)
    $ export SG=$(aws ec2 describe-security-groups --filters Name=vpc-id,Values="$VPC" --query 'SecurityGroups[?GroupName==`default`].GroupId | [0]' --output text)
    $ aws ecr create-repository --repository-name "$REPO" --image-scanning-configuration scanOnPush=true
    $ aws ecs create-cluster --cluster-name "$CLUSTER" --capacity-providers FARGATE
    $ cat > trust.json <<'JSON'
    {"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ecs-tasks.amazonaws.com"},"Action":"sts:AssumeRole"}]}
    JSON
    $ aws iam create-role --role-name "$ROLE" --assume-role-policy-document file://trust.json
    $ aws iam attach-role-policy --role-name "$ROLE" --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
    $ aws ecs register-task-definition --family "$FAMILY" --network-mode awsvpc --requires-compatibilities FARGATE --cpu 256 --memory 512 --execution-role-arn "arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):role/$ROLE" --container-definitions '[{"name":"web","image":"public.ecr.aws/docker/library/nginx:alpine","essential":true,"portMappings":[{"containerPort":80,"protocol":"tcp"}]}]'
    $ TASK=$(aws ecs run-task --cluster "$CLUSTER" --task-definition "$FAMILY" --launch-type FARGATE --network-configuration "awsvpcConfiguration={subnets=[$SUBNET],securityGroups=[$SG],assignPublicIp=ENABLED}" --query 'tasks[0].taskArn' --output text)
    $ aws ecs wait tasks-running --cluster "$CLUSTER" --tasks "$TASK"
    $ aws ecs describe-tasks --cluster "$CLUSTER" --tasks "$TASK" --query 'tasks[0].{Status:lastStatus,Definition:taskDefinition,Started:startedAt}' --output table
    -----------------------------------------------
    |              DescribeTasks                    |
    +----------+----------------------------------+
    | Status   | RUNNING                          |
    | Definition | ...:task-definition/academy-nginx |
    +----------+----------------------------------+
    $ aws ecs stop-task --cluster "$CLUSTER" --task "$TASK"
    $ aws ecs wait tasks-stopped --cluster "$CLUSTER" --tasks "$TASK"
    $ aws ecs deregister-task-definition --task-definition "$FAMILY":1
    $ aws ecs delete-cluster --cluster "$CLUSTER"
    $ aws ecr delete-repository --repository-name "$REPO" --force
    $ aws iam detach-role-policy --role-name "$ROLE" --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
    $ aws iam delete-role --role-name "$ROLE"
    $ aws ecs describe-clusters --clusters "$CLUSTER" --query 'clusters' --output json
    []
    $ aws ecr describe-repositories --repository-names "$REPO"
    An error occurred (RepositoryNotFoundException) when calling the DescribeRepositories operation
    
    aws ecr create-repository --repository-name "$REPO" --image-scanning-configuration scanOnPush=true
    • awsthe AWS command line
    cat > trust.json <<'JSON'
    • catprint a file
    • >write output to a file, replacing it
    aws ecs describe-tasks --cluster "$CLUSTER" --tasks "$TASK" --query 'tasks[0].{Status:lastStatus,Definition:taskDefinition,Started:startedAt}' --output table
    • --querypick fields from the JSON response
    • --outputoutput format

    The output shape above is from the real practice-account run; account-specific identifiers are intentionally omitted. If a command fails, stop and inspect before repeating it. Confirm the task is STOPPED before deleting its cluster, and confirm both the repository and role are gone.

    Try it yourself

    0 of 4 steps done

    Run each task in your own account or terminal, then tick it off.

    Knowledge check

    Quick check

    Question 1 of 7

    What does an ECR repository store?

    Go deeper

    Official reading for this lesson

    • DocsAmazon ECR User GuideAWS Docs ↗
    • DocsAmazon ECS Developer GuideAWS Docs ↗
    • GuideAmazon ECS task definitionsAWS Docs ↗
    • DocsAWS FargateAWS Docs ↗
    • DocsAmazon EKS User GuideAWS Docs ↗

    Or get every quiz answer right and it completes itself.

    ← PreviousManaged databases: RDS, DynamoDB, ElastiCacheNext lesson →Lambda: code without servers