This chapter covers ECS task definitions and container definitions, the foundational building blocks for running containers on AWS. Understanding these concepts is critical for the SAA-C03 exam, as approximately 10-15% of questions involve ECS, and task definitions are the core configuration element. You will learn the structure, parameters, and best practices for defining containers, including networking, storage, and IAM roles. Mastery of task definitions is essential for designing scalable, secure containerized applications on AWS.
Jump to a section
Think of an ECS task definition as a blueprint for a custom house. The blueprint specifies every detail: the number of rooms (containers), the materials required (images), the size of each room (CPU and memory), which doors lead outside (port mappings), and the wiring for electricity and plumbing (environment variables and secrets). The blueprint itself is a document—it doesn't build the house. When you want to construct a house, you give the blueprint to a builder (ECS), who then creates an actual house (task) based on that blueprint. If you need multiple identical houses, you reuse the same blueprint. If you later decide to add a garage (another container) or change the kitchen layout (update container definitions), you create a new version of the blueprint. The builder doesn't care about the old blueprint once the new one is approved. Similarly, in ECS, the task definition is a JSON document that defines one or more containers, their resources, networking, and storage. When you run a task or create a service, ECS uses the active revision of the task definition to launch the containers. The task definition itself is versioned, and changes require a new revision. This separation of definition from execution allows you to manage and version your container configurations independently from the running instances.
What is an ECS Task Definition?
An ECS task definition is a JSON document that describes how one or more containers should be launched. It is the blueprint for a task, which is the instantiation of the task definition. Task definitions are versioned; each revision is immutable, but you can create new revisions. The task definition includes:
Family: The logical name for the task definition (e.g., "my-app"). Revisions are numbered sequentially under the same family.
Container definitions: An array of container definitions, each specifying the image, CPU, memory, port mappings, environment variables, etc.
Task role: An IAM role that the task's containers can assume to access AWS services.
Task execution role: An IAM role used by ECS to pull images and publish logs.
Network mode: How the containers are networked (e.g., awsvpc, bridge, host, none).
Volumes: Data volumes that can be shared between containers or mounted from the host.
Placement constraints: Rules for where tasks can be placed (e.g., distinctInstance, memberOf).
Requires compatibilities: Whether the task uses Fargate or EC2 launch type (FARGATE, EC2, or EXTERNAL).
CPU and memory: For Fargate, these are specified at the task level; for EC2, they can be specified at the container level.
Container Definition Details
Each container definition in a task definition includes:
name: A unique name within the task definition.
image: The Docker image URI (e.g., "amazon/amazon-ecs-sample").
cpu: The number of CPU units reserved for the container. 1024 units = 1 vCPU. For EC2 launch type, this is optional; for Fargate, it is required at the task level.
memory and memoryReservation: memory is the hard limit (in MiB); memoryReservation is the soft limit. If only memoryReservation is set, the container can burst above it up to the instance's available memory.
portMappings: Maps container ports to host ports. For awsvpc mode, each container gets its own elastic network interface (ENI) with its own IP address. Port mappings can specify protocol (tcp/udp) and containerPort/hostPort. For awsvpc, hostPort must be the same as containerPort or omitted.
environment: An array of key-value pairs for environment variables. Values are plain text.
secrets: References to AWS Secrets Manager or Systems Manager Parameter Store for sensitive data. Uses the secrets manager or ssm parameter ARN.
logConfiguration: Specifies the log driver (e.g., awslogs) and options (e.g., awslogs-group, awslogs-region, awslogs-stream-prefix).
ulimits: Container ulimit settings (e.g., nofile, nproc).
dependsOn: Container dependency ordering. A container can depend on another container being in a certain status (START, COMPLETE, SUCCESS, HEALTHY).
healthCheck: A command to test container health (e.g., "CMD-SHELL", "curl -f http://localhost/ || exit 1").
essential: A boolean (default true). If an essential container fails, the entire task stops. If non-essential, the task continues.
linuxParameters: Includes capabilities, devices, tmpfs mounts, shared memory size, etc.
dockerLabels: Labels to apply to the container.
dockerSecurityOptions: Security options like "no-new-privileges".
systemControls: Namespaced kernel parameters (sysctls).
interactive and pseudoTerminal: For interactive containers (e.g., debugging).
readonlyRootFilesystem: If true, the container's root filesystem is read-only.
repositoryCredentials: For private registry authentication.
resourceRequirements: For GPU or Inferentia devices.
startTimeout and stopTimeout: Timeouts in seconds for container start/stop.
user: The user to run the container as.
workingDirectory: The working directory inside the container.
Network Modes
awsvpc: Each task gets its own ENI with a primary private IP address. This is required for Fargate and recommended for EC2. It provides the best network isolation and allows security groups to be attached at the task level. Port mappings must map container port to the same host port (or omitted, which defaults to the container port).
bridge: Uses Docker's built-in virtual network bridge. Containers are mapped to host ports via port mappings. This is the default for EC2 launch type if not specified.
host: The container's network stack is not isolated from the host. Port mappings are directly mapped to the host's network interface.
none: The container has no external network connectivity.
IAM Roles
Task execution role: Required for Fargate tasks. Used by the ECS agent to pull images from ECR or Docker Hub, and to send logs to CloudWatch. The role must have permissions like ecr:GetDownloadUrlForLayer, ecr:BatchGetImage, ecr:GetAuthorizationToken, and logs:CreateLogStream, logs:PutLogEvents.
Task role: An IAM role that the container's applications can assume via the AWS SDK or CLI. This is the role your application code uses to access AWS services. It is specified in the task definition's taskRoleArn.
Volumes and Mount Points
Volumes can be defined at the task level and mounted into containers via mountPoints. Types include:
bind: Mount a directory from the host's filesystem. Specified with sourcePath.
efs: Mount an Amazon EFS file system. Requires filesystemId and optional rootDirectory, transitEncryption, authorizationConfig.
dockerVolumeConfiguration: Use Docker volumes with options like scope (task or shared), autoprovision, driver, driverOpts, labels.
fsxWindowsFileServer: Mount an FSx for Windows File Server.
Mount points in container definitions have sourceVolume (name of the volume defined at task level) and containerPath.
Task Definition Parameters for Fargate vs EC2
Fargate: Requires requiresCompatibilities set to FARGATE. Network mode must be awsvpc. CPU and memory must be specified at the task level using specific combinations (e.g., 256 (.25 vCPU) with 512 MB, 1024 (1 vCPU) with 2048 MB, etc.). The task execution role is required.
EC2: requiresCompatibilities can be EC2 or omitted. Network mode can be any. CPU and memory can be specified at the container level or task level. Task execution role is optional but recommended.
Task Definition Lifecycle
Create: You register a new task definition with a family and revision. The first revision is 1.
Update: You cannot modify an existing revision. Instead, you register a new revision of the same family.
Deregister: You can deregister a task definition revision. It remains in the account but cannot be used to run new tasks. Existing tasks continue.
Delete: You cannot delete a task definition; you can only deregister it.
Example Task Definition (Fargate)
{
"family": "my-app",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789012:role/my-app-task-role",
"containerDefinitions": [
{
"name": "web",
"image": "nginx:latest",
"cpu": 256,
"memory": 512,
"essential": true,
"portMappings": [
{
"containerPort": 80,
"protocol": "tcp"
}
],
"environment": [
{"name": "ENV", "value": "production"}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-app",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "web"
}
}
}
]
}How Task Definitions Interact with Services and Tasks
Run Task: A task is a single instance of a task definition. You can run a task manually (e.g., for batch jobs) or as part of a service.
Service: An ECS service maintains a desired number of tasks running. It uses the task definition to launch new tasks when needed (e.g., during scaling, replacement). The service can use a specific revision of a task definition.
Scheduling: The ECS scheduler places tasks on container instances based on CPU/memory requirements, placement constraints, and availability.
Rolling Updates: When you update a service to use a new task definition revision, ECS performs a rolling update, replacing old tasks with new ones based on the deployment configuration.
Verification Commands
Register a task definition:
aws ecs register-task-definition --cli-input-json file://task-def.jsonList task definitions:
aws ecs list-task-definitions --family-prefix my-appDescribe a task definition:
aws ecs describe-task-definition --task-definition my-app:1Deregister a task definition:
aws ecs deregister-task-definition --task-definition my-app:1Default Values
essential: true
cpu: For EC2, if not specified, the container gets all available CPU on the instance (but subject to instance limits). For Fargate, cpu must be specified at task level.
memory: For EC2, if not specified, the container can use all available memory (up to instance limit). For Fargate, memory must be specified at task level.
networkMode: For EC2, default is bridge; for Fargate, must be awsvpc.
startTimeout: 30 seconds (default for Fargate) or 3 minutes (default for EC2).
stopTimeout: 30 seconds (default for Fargate) or 2 minutes (default for EC2).
Trap Patterns
Confusing task role with execution role: The task role is for the application; the execution role is for the ECS agent. The exam may ask which role to use for accessing S3 from your container code — answer: task role.
Thinking you can update a task definition in place: You cannot. You must create a new revision.
Assuming Fargate tasks can use bridge network mode: They cannot; only awsvpc is supported.
Assuming memoryReservation is a hard limit: It is a soft limit. The container can use more memory up to the hard limit (memory) or instance capacity.
Ignoring essential containers: If an essential container fails, the entire task stops. If you have a sidecar that can fail independently, set essential to false.
Define the container image and tag
Choose a Docker image from a registry (e.g., Amazon ECR, Docker Hub). The image URI must be specified in the container definition. For ECR, the format is `account-id.dkr.ecr.region.amazonaws.com/repository:tag`. If no tag is specified, `latest` is used. The ECS agent pulls the image during task launch. For private registries, repositoryCredentials must be provided.
Specify CPU and memory resources
For Fargate, you must specify CPU and memory at the task level using valid combinations (e.g., 256 CPU/512 MB, 512 CPU/1024 MB, 1024 CPU/2048 MB, etc.). For EC2, you can specify at the container level; if not specified, the container can use all available resources. The CPU unit is 1024 per vCPU. Memory is in MiB. If you specify both memory and memoryReservation, memory is the hard limit and memoryReservation is the soft limit.
Configure port mappings and network mode
For awsvpc mode, each task gets an ENI with its own IP. Port mappings must map containerPort to the same hostPort (or omit hostPort). For bridge mode, you can map container ports to dynamic host ports (hostPort=0) or specific ports. For host mode, the container uses the host's network directly. Choose the network mode based on isolation needs and launch type. Fargate requires awsvpc.
Set IAM roles for task and execution
The task execution role is used by ECS to pull images and send logs. It must have permissions for ECR and CloudWatch Logs. The task role is assumed by the container's application to access AWS services. Specify these roles in the task definition. For Fargate, the execution role is required. For EC2, it is optional but recommended.
Define environment variables and secrets
Environment variables can be plain text or referenced from AWS Secrets Manager or SSM Parameter Store using the `secrets` array. For secrets, specify the valueFrom as the ARN of the secret or parameter. The task execution role must have permission to read the secret. Use secrets for sensitive data like database passwords. For non-sensitive data, use environment.
Configure logging and container dependencies
Specify logConfiguration to send container logs to CloudWatch Logs, Splunk, or other destinations. For awslogs, you need to specify log group, region, and stream prefix. Use dependsOn to order container startup; for example, a web container can depend on a database container being healthy. The dependsOn condition can be START, COMPLETE, SUCCESS, or HEALTHY.
Register the task definition and launch tasks
Use the AWS CLI, SDK, or console to register the task definition. ECS assigns a revision number. You can then run a task manually or create a service that uses the task definition. The task definition is immutable; to make changes, register a new revision. When you update a service, you specify the new revision, and ECS performs a rolling update.
Enterprise Scenario 1: Microservices with Sidecar Containers
A large e-commerce company runs a microservices architecture on ECS with Fargate. Each service has a main application container and a sidecar container for logging and metrics. The task definition includes two container definitions: one for the app (e.g., Node.js) and one for the sidecar (e.g., Fluentd). The sidecar is marked as non-essential (essential: false) so that if it fails, the main container continues. The sidecar depends on the main container being healthy (dependsOn with condition HEALTHY). The task uses awsvpc network mode, and each task gets its own ENI, allowing security groups to restrict traffic to specific microservices. The company uses a task role for the main container to access DynamoDB and S3, and an execution role for pulling images from ECR. They register a new revision for each deployment, and the ECS service performs a rolling update with a 10% minimum healthy percent. Common misconfiguration: forgetting to set the sidecar as non-essential, causing the entire task to stop when the sidecar crashes.
Enterprise Scenario 2: Batch Processing with GPU
A media processing company uses ECS with EC2 launch type to run GPU-intensive transcoding jobs. The task definition specifies resourceRequirements for GPU (type GPU, value 1). The container image includes FFmpeg with GPU acceleration. The task uses host network mode for low latency, and the container mounts an EFS volume for input and output files. The task definition includes a volumes section with an efs volume configuration. The company runs tasks via RunTask API for each job, and the ECS scheduler places tasks on GPU-enabled instances. They use placement constraints to ensure tasks run only on instances with the required GPU driver. Common pitfall: not specifying the GPU resource requirement, leading to tasks being placed on non-GPU instances, causing the job to fail.
Enterprise Scenario 3: Multi-Container Pod with Shared Volume
A SaaS provider runs a web application with a WordPress container and a MySQL container in the same task. They use a shared volume for persistent data. The task definition defines a volume (bind mount from the host) and mounts it into both containers at /var/www/html. The MySQL container is essential, and the WordPress container depends on MySQL being healthy. They use bridge network mode on EC2 to allow container-to-container communication via localhost. Port mappings map MySQL port 3306 to a dynamic host port, and WordPress port 80 to port 80 on the host. The company uses an Application Load Balancer to route traffic to the WordPress container. Common issue: using awsvpc mode would give each container its own ENI, preventing localhost communication, so they must use bridge mode. Also, if the host instance fails, data on the bind mount is lost; they should use EFS for persistence.
The SAA-C03 exam tests your understanding of ECS task definitions under Domain 3: High Performance, Objective 3.3 (Select appropriate compute options). Expect 2-3 questions directly about task definitions, plus additional questions on related services like ECR, CloudWatch Logs, and IAM roles.
Common Wrong Answers and Why
"You can update an existing task definition revision to change container settings." This is false. Task definition revisions are immutable. You must register a new revision. Candidates often confuse this with updating a service, which references a new task definition revision.
"Fargate tasks can use bridge network mode." Fargate only supports awsvpc. Bridge mode is for EC2 launch type. The exam may present a scenario where you need to assign a security group to a task — that requires awsvpc, which implies Fargate or EC2 with awsvpc.
"The task execution role is used by the application to access AWS services." No, that's the task role. The execution role is for the ECS agent to pull images and send logs. The exam might ask which IAM role to grant S3 access to the container's code — answer: task role.
"Setting memoryReservation guarantees that amount of memory." memoryReservation is a soft limit; the container can use more up to the hard limit (memory) or instance capacity. It is not a guarantee. The exam may ask about resource allocation and overcommitment.
Specific Numbers and Terms
CPU units: 1024 = 1 vCPU
Fargate valid CPU/Memory combinations: e.g., 256 CPU with 512 MB, 512 CPU with 1024 MB, 1024 CPU with 2048 MB, etc. (full list in AWS docs).
Default essential: true
Default stopTimeout: 30s (Fargate), 2 min (EC2)
Default startTimeout: 30s (Fargate), 3 min (EC2)
awsvpc required for Fargate: Yes.
Task definition revision: Starts at 1, increments.
Edge Cases
Container dependency with HEALTHY condition: The health check must be defined in the container definition. If the health check fails, the dependent container may not start.
Using secrets with task execution role: The execution role must have permission to read the secret (e.g., secretsmanager:GetSecretValue).
Deregistering a task definition: It cannot be used to run new tasks, but existing tasks continue. The exam may ask about this lifecycle.
Multiple containers in a task: They share the same network namespace (except awsvpc gives each container its own ENI? Actually, in awsvpc mode, all containers in the same task share the same ENI — they can communicate via localhost. This is a common point of confusion).
How to Eliminate Wrong Answers
Identify the launch type first. If Fargate, network mode must be awsvpc.
Determine if the question is about application access (task role) or infrastructure access (execution role).
Check if the question implies modifying a task definition — if so, the answer must involve creating a new revision.
For resource allocation, if the question mentions "hard limit" and "soft limit", know that memory is hard, memoryReservation is soft.
For logging, if the question mentions CloudWatch Logs, the log driver is awslogs, and the execution role needs logs permissions.
Task definitions are immutable JSON blueprints for containers; changes require a new revision.
Fargate requires awsvpc network mode; EC2 supports multiple modes.
The task role is for application access to AWS services; the execution role is for ECS agent operations.
An essential container failure stops the entire task; non-essential containers do not.
Fargate CPU and memory must use specific valid combinations (e.g., 256 CPU with 512 MB).
memoryReservation is a soft limit; memory is a hard limit.
Secrets can be referenced from AWS Secrets Manager or SSM Parameter Store using the secrets array.
Container dependencies can order startup using dependsOn with conditions like HEALTHY.
Log configuration with awslogs driver sends logs to CloudWatch Logs.
Task definitions are versioned under a family; you can deregister old revisions.
These come up on the exam all the time. Here's how to tell them apart.
Fargate Launch Type
No need to manage underlying EC2 instances
Network mode must be awsvpc
CPU and memory must be specified at task level with valid combinations
Task execution role is required
Billing per second for vCPU and memory resources used
EC2 Launch Type
You manage the EC2 instances (scaling, patching)
Network mode can be awsvpc, bridge, host, or none
CPU and memory can be specified at container level or omitted
Task execution role is optional but recommended
Billing per EC2 instance (no per-task billing)
Mistake
You can edit an existing task definition revision.
Correct
Task definition revisions are immutable. You must register a new revision of the same family to make changes.
Mistake
Fargate tasks can use bridge or host network mode.
Correct
Fargate only supports awsvpc network mode. Bridge and host are only for EC2 launch type.
Mistake
The task execution role is used by the application code.
Correct
The task execution role is used by the ECS agent to pull images and send logs. The application uses the task role.
Mistake
memoryReservation is a hard memory limit.
Correct
memoryReservation is a soft limit; the container can burst above it up to the hard memory limit or instance capacity. The hard limit is set by the memory parameter.
Mistake
A non-essential container failure stops the entire task.
Correct
Only essential containers cause the task to stop if they fail. Non-essential containers can fail without affecting the task.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
The task execution role is used by the ECS agent to perform actions on your behalf, such as pulling container images from ECR and sending logs to CloudWatch Logs. The task role is used by the application running inside the container to access AWS services (e.g., S3, DynamoDB). For example, if your container needs to read from S3, you assign an IAM role with S3 read permissions to the task role. The execution role is required for Fargate and recommended for EC2.
No, because the required parameters differ. Fargate requires requiresCompatibilities set to FARGATE, network mode awsvpc, and specific CPU/memory combinations. EC2 can have different network modes and does not require CPU/memory at the task level. You would need separate task definitions for each launch type, or use a single task definition with requiresCompatibilities including both (but then you must meet the stricter Fargate requirements).
Use the secrets array in the container definition to reference AWS Secrets Manager secrets or Systems Manager Parameter Store parameters. Specify the valueFrom as the ARN of the secret or parameter. The task execution role must have permissions to read the secret. Do not use plain text environment variables for sensitive data.
Deregistering a task definition revision means it can no longer be used to run new tasks or create new services. However, any existing tasks that were launched using that revision continue to run. You cannot delete a task definition; you can only deregister it.
Yes, a task definition can contain multiple container definitions. They share the same lifecycle and are scheduled together on the same host (or same ENI for awsvpc). They can communicate via localhost if using bridge or awsvpc network mode. You can set dependencies between containers using the dependsOn parameter.
The default is true. If you do not specify essential, it defaults to true. If you have a sidecar container that can fail independently, you must explicitly set essential to false.
You cannot update the task definition revision. You must register a new revision with the desired changes, then update the service to use the new revision (e.g., via the AWS CLI: aws ecs update-service --service my-service --task-definition my-app:2). ECS will perform a rolling update.
You've just covered ECS Task Definitions and Container Definitions — now see how well it sticks with free SAA-C03 practice questions. Full explanations included, no account needed.
Done with this chapter?