Skip to main content
This guide walks through deploying a small Node.js + Express app to Amazon ECS using the Fargate launch type. We’ll first use the ECS quick start wizard to see what it creates automatically, then delete those resources and recreate everything manually so you understand each step.
  • Prerequisites: Docker (optional, for building images) and an AWS account with permissions to create ECS, IAM, VPC, and security group resources.
  • Public images used in this demo (available on Docker Hub):
    • KodeKloud/ECS-Project1
    • KodeKloud/ECS-Project2
Visit Docker Hub to pull and inspect the images before you begin:

Application (Project 1)

Project 1 is a minimal Node.js + Express app that serves a static HTML page at the root path. Example view file index.ejs:
Server code index.js:
Dockerfile:
Important: this app listens on container port 3000. When creating the container definition in ECS/Fargate, expose container port 3000. With Fargate (awsvpc network mode) ECS manages the host mapping and the container port is used to reach the application.

1) Quick start: use the ECS wizard

Open the AWS Console and search for “ECS” or go to the Amazon Elastic Container Service page. If this is your first time, the ECS quick start wizard can create a task definition, cluster, VPC, subnets, and a service for you. We’ll run the wizard once to inspect its defaults, then delete the created resources and perform the same steps manually. In the wizard choose a Custom container and provide values similar to:
  • Container name: ecs-project1
  • Image: KodeKloud/ECS-Project1
  • Memory limits: optional/sensible defaults
  • Port mappings: container port 3000 (TCP)
A screenshot of the AWS console for "Getting Started with Amazon Elastic Container Service (Amazon ECS) using Fargate," showing a diagram of ECS objects and a "Container definition" section. Several container options are listed (sample-app, nginx, tomcat-webserver, custom).
Example container configuration highlights:
  • Container port: 3000 (TCP)
  • Image: KodeKloud/ECS-Project1
  • Optional: memory, CPU, health checks, environment variables, logging
Health check example (container advanced settings):
A screenshot of the AWS Elastic Container Service task definition UI showing container settings (container name, image, memory limits) and a port mapping with container port 3000 set to TCP. The left side shows a faint diagram and example container cards.
The quick start wizard will populate logging and resource settings (for example, awslogs) with sensible defaults.
Screenshot of an AWS console task/container configuration page showing Log configuration, Resource Limits, and Docker Labels. The awslogs fields are filled (awslogs-group: /ecs/first-run-task-definition, awslogs-region: us-east-1, awslogs-stream-prefix: ecs).
Proceed through the wizard to create the task definition, service, and cluster. The quick start usually creates a new VPC and subnets (isolating the cluster) instead of using the account default VPC. Review the summary and create the service.
A screenshot of the AWS ECS console showing a diagram of ECS objects and a "Review" page summarizing a task definition and service configuration. Visible details include task name, network mode, container name, image, memory, port and protocol with Edit buttons beside sections.
When the wizard completes, view the created service in the cluster. The quick start normally creates the following resources for you:
A screenshot of the Amazon ECS console showing service "ecs-project1-service" in the "default" cluster with status ACTIVE, FARGATE launch type, and desired/running count 1. The page also shows task definition, no load balancers, and network access details (VPC, subnets, security group).
Task definitions are the blueprint for containers. In the Task Definitions page you should now see the task created by the wizard. Each revision of a task definition captures changes you make (a new revision is created when you edit and save).
A screenshot of the AWS Management Console showing the Amazon ECS "Task Definitions" page. It lists several task definitions (bakend, ecs-project2, ecsprod2, first-run-task-definition, test1) with their latest revision statuses marked ACTIVE.
Open the task definition to inspect container configuration, CPU/memory, and port mappings (3000 → 3000 in this demo). Revisions increment when you make and save changes.
A screenshot of the AWS Management Console showing an ECS task definition page with task execution IAM role, task memory/CPU sliders, and resource allocation bars. The Container definitions section lists a container named "ecs-project1" with a host/container port mapping of 3000 (TCP).
Open the Clusters page and select the cluster created by the wizard. With Fargate you won’t see underlying EC2 instances; if you had used the EC2 launch type, you’d see the EC2 instances hosting tasks. Click the Service to view Tasks. Each running task shows network details, including a public IP (if enabled). Use the public IP and the container port to access the app: http://<public-ip>:3000
A screenshot of an Amazon ECS task details page showing a FARGATE task with status "RUNNING." The Network section is visible with private/public IP and ENI information, and a containers list showing a running container named ecs-project1.

2) Clean up wizard resources (so we can recreate manually)

To learn the underlying steps, delete the resources the wizard created:
  • Delete the service (stops and removes tasks).
  • Delete the cluster (removes cluster and the VPC/subnets the wizard created).
After cleanup, create a cluster manually.

3) Create a cluster and task definition manually

Create a new cluster:
  • Go to ECS → Clusters → Create Cluster
  • Choose “Networking only (Fargate)”
  • Name the cluster, e.g., cluster1
  • Let ECS create a VPC and subnets for you (or choose an existing VPC)
  • Create and open the cluster
Next, create a Task Definition:
  • ECS → Task Definitions → Create task definition → select FARGATE
  • Name the task definition and select the Task execution role (this role lets ECS pull images and write logs)
  • OS family: Linux
  • Set Task CPU and Memory appropriate to your app
  • Add a container definition:
    • Container name: node-app
    • Image: KodeKloud/ECS-Project1
    • Port mapping: container port 3000, TCP
    • Optionally: health check, env vars, logging (awslogs)
A screenshot of the AWS Management Console (ECS task definition) showing the "Task execution IAM role" and "Task size" sections. The Task memory dropdown is expanded with memory options visible and an "Add container" button below.
After creating the task definition, create a service to run tasks from it. Service creation checklist:
  • Cluster → Services → Create
  • Launch type: FARGATE
  • Task definition: select your newly created task definition (latest revision)
  • Cluster: cluster1
  • Service name: project-one-service
  • Number of tasks: desired scale (e.g., 1 or 2)
  • Networking:
    • VPC and subnets: choose those created for the cluster
    • Security group: ensure it allows inbound traffic to the container port (3000) from the clients that need access
  • Load balancer: optional (skipped in this demo)
  • Auto Scaling: optional (skip for the demo)
A screenshot of the AWS web console showing an ECS service configuration form with fields like Operating system family, Task Definition, Cluster, Service name, Number of tasks, and deployment options.
Be careful when opening security groups to the internet. For demo purposes you may allow 0.0.0.0/0 to port 3000, but for production use least-privilege rules or a load balancer with restrictive access.
When configuring the service security group, add an inbound rule permitting TCP access to 3000 from the required CIDR range.
A screenshot of the AWS console showing the "Create Service" network configuration with a "Configure security groups" dialog open. The dialog defines a security group (projec-4524) with an inbound Custom TCP rule allowing port 3000 from Anywhere (0.0.0.0/0).
Create the service. If you requested multiple tasks, ECS will provision the requested number of tasks using the same task definition. Tasks may show PENDING or PROVISIONING while Fargate allocates ENIs and networking; they will move to RUNNING once ready.
A screenshot of the AWS ECS console showing the "project1-service" service details for cluster1 (status ACTIVE) with desired count 2. The tasks table shows one task RUNNING and one PENDING under the FARGATE launch type.
Each running Fargate task receives its own ENI and IP address (public IP if enabled). Inspect a task to find its IP address and test the app with: http://<task-public-ip>:3000
A screenshot of the Amazon ECS console showing details for a Fargate task (cluster "cluster1") with status RUNNING and a listed container named "node-app." The page displays task metadata and network info such as platform version, task definition, ENI/subnet, and IP addresses.
Try both task IPs (if you created multiple tasks) to confirm the app responds. Because each task has a different IP, production deployments typically use a load balancer to present a single endpoint and distribute traffic to healthy tasks.

4) Updating the app image and redeploying

If you change application code (for example, modify the HTML view), rebuild and push a new Docker image to your registry (Docker Hub in this demo). ECS will not automatically pull the new image until you trigger a deployment. Example local steps (build and push):
Ways to make ECS pull the updated image and restart containers:
  • In the Service view: Choose Update → check “Force new deployment” — this causes ECS to create new tasks that pull the updated image.
  • Or: Create a new revision of the Task Definition (if you changed configuration) and update the service to use that revision.
To create a new revision of a task definition: open the existing task definition, click “Create new revision”, save changes, then update the service to use the new revision. ECS will start new tasks (pulling the updated image/config) and, once healthy, stop the old tasks. Because task IPs change during deployments, a load balancer avoids the need for clients to track task IPs.
A screenshot of the AWS Management Console showing the "Create new revision of Task Definition" page for Amazon ECS, with fields for task definition name, task role, network mode (awsvpc), and FARGATE selected. The lower section shows task execution IAM role and task size settings (memory and CPU).
While a deployment rolls out, the service will show additional tasks in PROVISIONING or RUNNING states as old tasks are replaced.
A screenshot of an AWS ECS service details page for "project1-service." It shows cluster and task definition info plus a table of FARGATE tasks with statuses like PROVISIONING and RUNNING.
After the deployment finishes, verify the new tasks are running with the updated image.

5) Final cleanup and next steps

When finished with the demo resources:
  • Delete the service (this will stop tasks).
  • Delete the cluster (if you don’t plan to reuse it).
  • Delete any related security groups, VPCs, or load balancers the demo created (if applicable).
If you plan to continue experimenting, consider deploying a more complex architecture (database backend, persistent volumes, and an Application Load Balancer) and explore service discovery for internal communication. Helpful references: Good luck — and remember to monitor costs for demo resources in your AWS account.

Watch Video