There are three kinds of launch types for Amazon Elastic Container Service. According to the official documentation, they are:
- Fargate launch type
- EC2 launch type
- External launch type
Choose AWS Fargate for a serverless flavour, eliminating the need to manage backend infrastructure. If you want to control the Amazon ECS cluster yourself, choose the EC2 option. Finally, use the External launch type to run containerized applications on an on-premises server or a virtual machine.
This blog will look at the 2 ECS launch types—the Fargate launch type and the EC2 launch type. Let’s get starte
ECS Task with EC2 Launch Type
The first type we will start with is the EC2 Launch Type.
Using AWS Console
Step 1: Go to ECS >> Clusters
Step 2: Select the ECS cluster created. For more, see Creating an ECS Cluster (AWS/Creating an-ECS-Cluster).
Step 3: Select Task Definitions >> Create a new Task Definition.
Step 4: Select Launch Type Compatibility.
Step 5: Select EC2 and click on Next Step.
Step 6: Configure the task and container definition. Define it with values as shown below. Make sure ecsTaskExecutionRole is selected for Task Role. It is needed to make API calls to authorised AWS services.


Step 8: Specify the Task size for the whole Task (total for all containers). Memory and vCPU are needed for the Task. This is optional for EC2 Launch type as the resources depend on the EC2 instance.
Step 9: There are many sub-parts to this step.
- Fill in the container definitions by clicking Add Container.
- Provide a container name.
- Provide the image name. This can be an URL to a Public/Private ECR/Docker Repository. Private Repositories other than AWS ECR may need authentication. The authentication credentials can be configured using Secrets Manager (AWS/Storing-Credentials-in-AWS-Secrets-Manager).
- Set the Memory Limit for the particular container. Hard Limit should be greater than or equal to Soft Limit.
- Add the Port Mappings (Host: Container).
- Provide the rest of the settings as per your needs. The above settings are enough for a container to get running.
- Additionally, we can configure Health check Parameters, Environment Variables, Timeout, CPU Units and other Settings. Mounting and adding volumes to the Docker container is done in the Storage and Logging section.
- Click Add to add the container definition.
Step 10: Enable the rest of the settings as per requirement. To add persistent volumes for Docker, go to Volumes >> Add Volume and specify the mount points.
Step 11: Click Create. You have completed the process!
Using AWS CLI (EC2 Launch Type)
Step 1: Set up AWS CLI (https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) in the local machine.
Step 2: To create a task definition with a single container, run the following command with container definitions in JSON format.
aws ecs register-task-definition –family nginx-cli –task-role-arn ecsTaskExecutionRole –network-mode bridge –execution-role-arn ecsTaskExecutionRole –requires-compatibilities EC2 –cpu 512 –memory 1024 –container-definitions ” [{\”name\”:\”nginx\”,\”image\”:\”242526598623.dkr.ecr.ap-south 1.amazonaws.com/nginx:latest\”,\”cpu\”:512,\”memory\”:1024,\”memoryReser vation\”:1024,\”portMappings\”: [{\”containerPort\”: 80,\”hostPort\”: 80,\”protocol\”: \”tcp\”}],\”essential\”:true}]” |
OUTPUT:
{
“taskDefinition”: {
“taskDefinitionArn”: “arn:aws:ecs:ap-south-1:242526598623:task definition/nginx-cli:1”,
“containerDefinitions”: [
{
“name”: “nginx-cli”,
“image”: “242526598623.dkr.ecr.ap-south
1.amazonaws.com/nginx:latest”,
“cpu”: 256,
“memory”: 512,
“memoryReservation”: 512,
“portMappings”: [
{
“containerPort”: 80,
“hostPort”: 80,
“protocol”: “tcp”
}
],
“essential”: true,
“environment”: [],
“mountPoints”: [
{
“sourceVolume”: “Data”,
“containerPath”: “/data/db/”,
“readOnly”: false
}
],
“volumesFrom”: []
}
],
“family”: “nginx-cli”,
“taskRoleArn”:
“arn:aws:iam::242526598623:role/ecsTaskExecutionRole”, “executionRoleArn”:
“arn:aws:iam::242526598623:role/ecsTaskExecutionRole”, “networkMode”: “bridge”,
“revision”: 1,
“volumes”: [
{
“name”: “Data”,
“host”: {
“sourcePath”: “/data/db”
}
}
],
“status”: “ACTIVE”,
“requiresAttributes”: [
{
“name”: “com.amazonaws.ecs.capability.ecr-auth”
},
{
“name”: “com.amazonaws.ecs.capability.docker-remote api.1.21”
},
{
“name”: “com.amazonaws.ecs.capability.task-iam-role” },
{
“name”: “ecs.capability.execution-role-ecr-pull”
}
],
“placementConstraints”: [],
“compatibilities”: [
“EXTERNAL”,
“EC2”
],
“requiresCompatibilities”: [
“EC2”
],
“cpu”: “512”,
“memory”: “1024”,
“registeredAt”: “2021-07-03T21:46:39.876000+05:30”,
“registeredBy”:
“arn:aws:iam::242526598623:user/dawn.mathews@piserve.com”
}
}
Step 3: Create a container with multiple containers. It is similar to the above command having the second container’s definition in JSON format.
In the case of EC2 tasks, verify the available memory in EC2 instances.
For example, for an EC2 instance with 1 GB memory, the actual available memory will be less than 900 MB. It will be only reflected while creating the container. So keep at least 100 MB as a buffer.
The command is given below.
aws ecs register-task-definition –family mongo-app –task-role-arn arn:aws:iam::242526598623:role/ecsTaskExecutionRole –network-mode bridge –execution-role-arn arn:aws:iam::242526598623:role/ecsTaskExecutionRole –requires compatibilities EC2 –cpu 512 –memory 1024 –container-definitions ” [{\”name\”:\”nginx\”,\”image\”:\”242526598623.dkr.ecr.ap-south 1.amazonaws.com/nginx:latest\”,\”cpu\”:256,\”memory\”:440,\”memoryReserv ation\”:440,\”portMappings\”: [{\”containerPort\”: 80,\”hostPort\”: 80,\”protocol\”: \”tcp\”}],\”essential\”:true}, {\”name\”:\”mongo\”,\”image\”:\”mongo\”,\”cpu\”:256,\”memory\”:440,\”mem oryReservation\”:440,\”portMappings\”: [{\”containerPort\”: 27017,\”hostPort\”: 27017,\”protocol\”: \”tcp\”}],\”essential\”:true}]” |
OUTPUT:
{
“taskDefinition”: {
“taskDefinitionArn”: “arn:aws:ecs:ap-south-1:242526598623:task definition/mongo-app:1”,
“containerDefinitions”: [
{
“name”: “nginx”,
“image”: “242526598623.dkr.ecr.ap-south
1.amazonaws.com/nginx:latest”,
“cpu”: 256,
“memory”: 440,
“memoryReservation”: 440,
“portMappings”: [
{
“containerPort”: 80,
“hostPort”: 80,
“protocol”: “tcp”
}
],
“essential”: true,
“environment”: [],
“mountPoints”: [],
“volumesFrom”: []
},
{
“name”: “mongo”,
“image”: “mongo”,
“cpu”: 256,
“memory”: 440,
“memoryReservation”: 440,
“portMappings”: [
{
“containerPort”: 27017,
“hostPort”: 27017,
“protocol”: “tcp”
}
],
“essential”: true,
“environment”: [],
“mountPoints”: [],
“volumesFrom”: []
}
],
“family”: “mongo-app”,
“taskRoleArn”:
“arn:aws:iam::242526598623:role/ecsTaskExecutionRole”, “executionRoleArn”:
“arn:aws:iam::242526598623:role/ecsTaskExecutionRole”, “networkMode”: “bridge”,
“revision”: 1,
“volumes”: [],
“status”: “ACTIVE”,
“requiresAttributes”: [
{
“name”: “com.amazonaws.ecs.capability.ecr-auth”
},
{
“name”: “com.amazonaws.ecs.capability.docker-remote api.1.21”
},
{
“name”: “com.amazonaws.ecs.capability.task-iam-role” },
{
“name”: “ecs.capability.execution-role-ecr-pull”
}
],
“placementConstraints”: [],
“compatibilities”: [
“EXTERNAL”,
“EC2”
],
“requiresCompatibilities”: [
“EC2”
],
“cpu”: “512”,
“memory”: “1024”,
“registeredAt”: “2021-07-03T21:57:31.176000+05:30”,
“registeredBy”:
“arn:aws:iam::242526598623:user/dawn.mathews@piserve.com”
}
}
Step 4: Create a container with a persistent volume attached to a container. Specify the mount point name in the container definition. The Volume should be mounted to be used by the container.
aws ecs register-task-definition –family app-mongo –task-role-arn arn:aws:iam::242526598623:role/ecsTaskExecutionRole –network-mode bridge –execution-role-arn arn:aws:iam::242526598623:role/ecsTaskExecutionRole –requires compatibilities EC2 –cpu 512 –memory 900 –volumes “[{\”name\”: \”Data\”,\”host\”: {\”sourcePath\”: \”/data/db\”}}]” –container definitions “[{\”name\”:\”nginx cli\”,\”image\”:\”242526598623.dkr.ecr.ap-south 1.amazonaws.com/nginx:latest\”,\”cpu\”:256,\”memory\”:400,\”memoryReserv ation\”:400,\”portMappings\”: [{\”containerPort\”: 80,\”hostPort\”: 80,\”protocol\”: \”tcp\”}],\”essential\”:true}, {\”name\”:\”mongo\”,\”image\”:\”mongo\”,\”cpu\”:256,\”memory\”:400,\”mem oryReservation\”:400,\”portMappings\”: [{\”containerPort\”: 27017,\”hostPort\”: 27017,\”protocol\”: \”tcp\”}],\”essential\”:true,\”mountPoints\”: [{\”readOnly\”: false,\”containerPath\”: \”/data/db/\”,\”sourceVolume\”: \”Data\”}]}]” |
OUTPUT:
{
“taskDefinition”: {
“taskDefinitionArn”: “arn:aws:ecs:ap-south-1:242526598623:task definition/nginx-cli:29”,
“containerDefinitions”: [
{
“name”: “app-mongo”,
“image”: “242526598623.dkr.ecr.ap-south
1.amazonaws.com/nginx:latest”,
“cpu”: 256,
“memory”: 400,
“memoryReservation”: 400,
“portMappings”: [
{
“containerPort”: 80,
“hostPort”: 80,
“protocol”: “tcp”
}
],
“essential”: true,
“environment”: [],
“mountPoints”: [],
“volumesFrom”: []
},
{
“name”: “mongo”,
“image”: “mongo”,
“cpu”: 256,
“memory”: 400,
“memoryReservation”: 400,
“portMappings”: [
{
“containerPort”: 27017,
“hostPort”: 27017,
“protocol”: “tcp”
}
],
“essential”: true,
“environment”: [],
“mountPoints”: [
{
“sourceVolume”: “Data”,
“containerPath”: “/data/db/”,
“readOnly”: false
}
],
“volumesFrom”: []
}
],
“family”: “nginx-cli”,
“taskRoleArn”:
“arn:aws:iam::242526598623:role/ecsTaskExecutionRole”, “executionRoleArn”:
“arn:aws:iam::242526598623:role/ecsTaskExecutionRole”, “networkMode”: “bridge”,
“revision”: 1,
“volumes”: [
{
“name”: “Data”,
“host”: {
“sourcePath”: “/data/db”
}
}
],
“status”: “ACTIVE”,
“requiresAttributes”: [
{
“name”: “com.amazonaws.ecs.capability.ecr-auth”
},
{
“name”: “com.amazonaws.ecs.capability.docker-remote api.1.21”
},
{
“name”: “com.amazonaws.ecs.capability.task-iam-role”
},
{
“name”: “ecs.capability.execution-role-ecr-pull”
}
],
“placementConstraints”: [],
“compatibilities”: [
“EXTERNAL”,
“EC2”
],
“requiresCompatibilities”: [
“EC2”
],
“cpu”: “512”,
“memory”: “900”,
“registeredAt”: “2021-07-03T22:11:23.593000+05:30”,
“registeredBy”:
“arn:aws:iam::242526598623:user/dawn.mathews@piserve.com”
}
}
ECS Task with Fargate Launch Type
Here are the steps of the Fargate Launch Type.
Step 1: Go to ECS >> Clusters.
Step 2: Select the ECS cluster created. For more, see Creating an ECS Cluster (AWS/Creating an-ECS-Cluster).
Step 3: Select Task Definitions >> Create a new Task Definition.
Step 4: Select Launch Type Compatibility. Select FARGATE and Click on Next Step.
Step 5: Configure the task and container definition. Define it with values as shown below. We select Task Role as ecsTaskExecutionRole. It is needed to make API calls to authorised AWS services. The Network Mode for Fardate is awsvpc by default.
Step 6: Select ecsTaskExecutionRole in Task execution role.
Step 7: Specify the Task size for the whole Task (Total for all containers). Next, specify the Memory and vCPU needed for the Task. You should choose this depending on your task requirements. Keep in mind the daemon requirements and the maximum number of tasks to run.
Step 8: This step is divided into different sub-steps.
- Create the container definition by clicking on Add Container.
- Provide a suitable name for this container.
- Give it an image name. For example, it can be an URL to a Public/Private ECR/Docker Repository. Private Repositories other than AWS ECR may need authentication.
- The authentication credentials can be configured using Secrets Manager (AWS/Storing-Credentials-in-AWS-Secrets-Manager).
- Set the Memory Limits (Hard Limit should be greater than or equal to Soft Limit) for the container.
- Add the Port Mappings (Container Port). The container will listen on this port when run as a Fargate service with awsvpc network mode.
[Note: Host port mappings are not valid when the network mode for a task definition is host or awsvpc. Select the Bridge network mode to specify different host and container port mappings, if needed].
- Provide the rest of the settings in Advanced container configuration as per the requirement.
- Click Add to add the container definition.
Step 9: Back to the task creation screen and configure the extra parameters needed.
To add Volumes to the container, Go to Volumes >> Add Volume.
Give the name of the Volume. If you plan to use the Volume in host mode, select Bind Volume in Volume Type.
However, select EFS if you would like to add EFS volume for persistence. Also, configure Mount Points under STORAGE AND LOGGING in the Add Container section.
10. Click Create.
Using AWS CLI (Fargate Launch Type)
We will now describe the same process for the Command Line Interface method.
Step 1: Creating Task definition via AWS CLI with launch type Fargate requires minor changes from EC2 launch type. Fargate supports only awsvpc network mode. Also, the volumes to be mounted do not need a source path.
aws ecs register-task-definition –family nginx –task-role-arn ecsTaskExecutionRole –network-mode awsvpc –execution-role-arn ecsTaskExecutionRole –requires-compatibilities FARGATE –cpu 512 — memory 1024 –container-definitions ” [{\”name\”:\”nginx\”,\”image\”:\”242526598623.dkr.ecr.ap-south 1.amazonaws.com/nginx:latest\”,\”cpu\”:512,\”memory\”:1024,\”memoryReser vation\”:1024,\”portMappings\”: [{\”containerPort\”: 80,\”hostPort\”: 80,\”protocol\”: \”tcp\”}],\”essential\”:true}]” |
OUTPUT:
{
“taskDefinition”: {
“taskDefinitionArn”: “arn:aws:ecs:ap-south-1:242526598623:task definition/nginx:4”,
“containerDefinitions”: [
{
“name”: “nginx”,
“image”: “242526598623.dkr.ecr.ap-south
1.amazonaws.com/nginx:latest”,
“cpu”: 512,
“memory”: 1024,
“memoryReservation”: 1024,
“portMappings”: [
{
“containerPort”: 80,
“hostPort”: 80,
“protocol”: “tcp”
}
],
“essential”: true,
“environment”: [],
“mountPoints”: [],
“volumesFrom”: []
}
],
“family”: “nginx”,
“taskRoleArn”:
“arn:aws:iam::242526598623:role/ecsTaskExecutionRole”,
“executionRoleArn”:
“arn:aws:iam::242526598623:role/ecsTaskExecutionRole”,
“networkMode”: “awsvpc”,
“revision”: 4,
“volumes”: [],
“status”: “ACTIVE”,
“requiresAttributes”: [
{
“name”: “com.amazonaws.ecs.capability.ecr-auth”
},
{
“name”: “com.amazonaws.ecs.capability.docker-remote
api.1.21″
},
{
“name”: “com.amazonaws.ecs.capability.task-iam-role”
},
{
“name”: “ecs.capability.execution-role-ecr-pull”
},
{
“name”: “com.amazonaws.ecs.capability.docker-remote
api.1.18″
},
{
“name”: “ecs.capability.task-eni”
}
],
“placementConstraints”: [],
“compatibilities”: [
“EC2”,
“FARGATE”
],
“requiresCompatibilities”: [
“FARGATE”
],
“cpu”: “512”,
“memory”: “1024”,
“registeredAt”: “2021-07-03T22:54:44.012000+05:30”,
“registeredBy”:
“arn:aws:iam::242526598623:user/dawn.mathews@piserve.com”
}
}
Step 2: The next step to create a Fargate task with multiple containers and persisitent volumes.
aws ecs register-task-definition –family mongo-app –task-role-arn arn:aws:iam::242526598623:role/ecsTaskExecutionRole –network-mode awsvpc –execution-role-arn arn:aws:iam::242526598623:role/ecsTaskExecutionRole –requires compatibilities EC2 –cpu 512 –memory 1024 –volumes “[{\”name\”: \”Data\”,\”host\”: {\”sourcePath\”: \”/data/db\”}}]” –container definitions “[{\”name\”:\”nginx\”,\”image\”:\”242526598623.dkr.ecr.ap south 1.amazonaws.com/nginx:latest\”,\”cpu\”:256,\”memory\”:512,\”memoryReserv ation\”:512,\”mountPoints\”: [{\”readOnly\”: false,\”containerPath\”: \”/data/db/\”,\”sourceVolume\”: \”Data\”}],\”portMappings\”: [{\”containerPort\”: 80,\”hostPort\”: 80,\”protocol\”: \”tcp\”}],\”essential\”:true}]” |
OUTPUT:
{
“taskDefinition”: {
“taskDefinitionArn”: “arn:aws:ecs:ap-south-1:242526598623:task definition/nginx-cli:30”,
“containerDefinitions”: [
{
“name”: “nginx”,
“image”: “242526598623.dkr.ecr.ap-south
1.amazonaws.com/nginx:latest”,
“cpu”: 256,
“memory”: 512,
“memoryReservation”: 512,
“portMappings”: [
{
“containerPort”: 80,
“hostPort”: 80,
“protocol”: “tcp”
}
],
“essential”: true,
“environment”: [],
“mountPoints”: [],
“volumesFrom”: []
},
{
“name”: “mongo”,
“image”: “mongo”,
“cpu”: 256,
“memory”: 512,
“memoryReservation”: 512,
“portMappings”: [
{
“containerPort”: 27017,
“hostPort”: 27017,
“protocol”: “tcp”
}
],
“essential”: true,
“environment”: [],
“mountPoints”: [
{
“sourceVolume”: “Data”,
“containerPath”: “/data/db/”,
“readOnly”: false
}
],
“volumesFrom”: []
}
],
“family”: “mongo-app”,
“taskRoleArn”:
“arn:aws:iam::242526598623:role/ecsTaskExecutionRole”, “executionRoleArn”:
“arn:aws:iam::242526598623:role/ecsTaskExecutionRole”, “networkMode”: “awsvpc”,
“revision”: 30,
“volumes”: [
{
“name”: “Data”,
“host”: {}
}
],
“status”: “ACTIVE”,
“requiresAttributes”: [
{
“name”: “com.amazonaws.ecs.capability.ecr-auth”
},
{
“name”: “com.amazonaws.ecs.capability.docker-remote api.1.21”
},
{
“name”: “com.amazonaws.ecs.capability.task-iam-role” },
{
“name”: “ecs.capability.execution-role-ecr-pull”
},
{
“name”: “com.amazonaws.ecs.capability.docker-remote api.1.18”
},
{
“name”: “ecs.capability.task-eni”
}
],
“placementConstraints”: [],
“compatibilities”: [
“EC2”,
“FARGATE”
],
“requiresCompatibilities”: [
“FARGATE”
],
“cpu”: “512”,
“memory”: “1024”,
“registeredAt”: “2021-07-03T22:44:44.528000+05:30”, “registeredBy”:
“arn:aws:iam::242526598623:user/dawn.mathews@piserve.com” }
}
Register a task definition using JSON file.
1. Create a JSON file “task-def.json” in the format required for ECS task definition. Please see the contents of file below.
<details>
<summary>Expand to see <b>task-def.json</b></summary>
{
“executionRoleArn”:
“arn:aws:iam::242526598623:role/ecsTaskExecutionRole”,
“containerDefinitions”: [
{
“portMappings”: [
{
“hostPort”: 80,
“protocol”: “tcp”,
“containerPort”: 80
}
],
“cpu”: 256,
“memory”: 512,
“memoryReservation”: 512,
“image”: “242526598623.dkr.ecr.ap-south
1.amazonaws.com/nginx:latest”,
“essential”: true,
“name”: “mongo-app”
},
{
“portMappings”: [
{
“hostPort”: 27017,
“protocol”: “tcp”,
“containerPort”: 27017
}
],
“cpu”: 256,
“mountPoints”: [
{
“readOnly”: false,
“containerPath”: “/data/db/”,
“sourceVolume”: “Data”
}
],
“memory”: 512,
“memoryReservation”: 512,
“image”: “mongo”,
“essential”: true,
“name”: “mongo”
}
],
“placementConstraints”: [],
“memory”: “1024”,
“taskRoleArn”: “arn:aws:iam::242526598623:role/ecsTaskExecutionRole”, “family”: “nginx-cli”,
“requiresCompatibilities”: [
“FARGATE”
],
“networkMode”: “awsvpc”,
“cpu”: “512”,
“volumes”: [
{
“name”: “Data”
}
]
}
</details>
Step 3: Run the following command to register the task definition.
aws ecs register-task-definition –cli-input-json file://task-def.json |
OUTPUT:
{
“taskDefinition”: {
“taskDefinitionArn”: “arn:aws:ecs:ap-south-1:242526598623:task definition/mongo-app:2”,
“containerDefinitions”: [
{
“name”: “nginx”,
“image”: “242526598623.dkr.ecr.ap-south
1.amazonaws.com/nginx:latest”,
“cpu”: 256,
“memory”: 512,
“memoryReservation”: 512,
“portMappings”: [
{
“containerPort”: 80,
“hostPort”: 80,
“protocol”: “tcp”
}
],
“essential”: true,
“environment”: [],
“mountPoints”: [],
“volumesFrom”: []
},
{
“name”: “mongo”,
“image”: “mongo”,
“cpu”: 256,
“memory”: 512,
“memoryReservation”: 512,
“portMappings”: [
{
“containerPort”: 27017,
“hostPort”: 27017,
“protocol”: “tcp”
}
],
“essential”: true,
“environment”: [],
“mountPoints”: [
{
“sourceVolume”: “Data”,
“containerPath”: “/data/db/”,
“readOnly”: false
}
],
“volumesFrom”: []
}
],
“family”: “mongo-app”,
“taskRoleArn”:
“arn:aws:iam::242526598623:role/ecsTaskExecutionRole”, “executionRoleArn”:
“arn:aws:iam::242526598623:role/ecsTaskExecutionRole”, “networkMode”: “awsvpc”,
“revision”: 32,
“volumes”: [
{
“name”: “Data”,
“host”: {}
}
],
“status”: “ACTIVE”,
“requiresAttributes”: [
{
“name”: “com.amazonaws.ecs.capability.ecr-auth”
},
{
“name”: “com.amazonaws.ecs.capability.docker-remote api.1.21”
},
{
“name”: “com.amazonaws.ecs.capability.task-iam-role” },
{
“name”: “ecs.capability.execution-role-ecr-pull”
},
{
“name”: “com.amazonaws.ecs.capability.docker-remote api.1.18”
},
{
“name”: “ecs.capability.task-eni”
}
],
“placementConstraints”: [],
“compatibilities”: [
“EC2”,
“FARGATE”
],
“requiresCompatibilities”: [
“FARGATE”
],
“cpu”: “512”,
“memory”: “1024”,
“registeredAt”: “2021-07-07T20:28:53.013000+05:30”, “registeredBy”:
“arn:aws:iam::242526598623:user/dawn.mathews@piserve.com” }
}
Wrapping Up
One cannot run an application on Amazon ECS without a task definition. A task definition is a text file in JSON that describes the containers which form your application. Hence, the launch types for the task definitions is a crucial factor.
At SysAlly, we experiment with Cloud and the most useful information is passed on to the world as blogs. Signup for the updates.
Until later, here’s SysAlly signing off!