The most surprising thing about ECS network modes is that awsvpc isn’t just a networking mode; it’s a fundamental shift in how your tasks interact with AWS networking, treating each task like a first-class VPC resource.
Let’s see awsvpc in action. Imagine you have a simple web service running in ECS.
{
"family": "my-web-app",
"containerDefinitions": [
{
"name": "web",
"image": "nginx:latest",
"portMappings": [
{
"containerPort": 80,
"hostPort": 80,
"protocol": "tcp"
}
],
"essential": true
}
],
"requiresCompatibilities": [
"FARGATE"
],
"networkMode": "awsvpc",
"cpu": "256",
"memory": "512"
}
When you launch a task with this definition in Fargate, ECS provisions an Elastic Network Interface (ENI) directly for that specific task. This ENI gets its own IP address from the subnet you’ve specified in your task definition or service configuration. It’s as if your container is a resource within your VPC, not just something running on an EC2 instance.
This awsvpc mode is the default and recommended mode for Fargate because it offers the most granular control and security. Each task gets its own ENI, its own IP address, and its own security group. This means you can apply security group rules directly to the task, just like you would for a traditional EC2 instance. You can also control which subnets your tasks launch into, allowing for fine-grained network segmentation.
Contrast this with the bridge network mode. In bridge mode, tasks run on an EC2 instance that has its own ENI. The container networking is managed by Docker’s bridge network, which creates an internal network for containers on that host. Ports are then mapped from the host EC2 instance’s IP address to the container’s port. This means multiple tasks on the same EC2 instance share the host’s IP address for external communication, and you manage access through the EC2 instance’s security group.
The host network mode is even simpler. Here, the container shares the network namespace of the host EC2 instance. There’s no port mapping; the container’s ports are directly exposed on the host’s IP address. This offers the best network performance as there’s no overlay network, but it sacrifices isolation. All tasks on the host share the same IP, and any port opened by one task is available to all others. This mode is generally not recommended for security reasons unless you have a very specific use case and control your network environment tightly.
The core problem awsvpc solves is the lack of direct network identity for individual tasks. In older modes, tasks were somewhat ephemeral network entities "behind" an EC2 instance. awsvpc elevates tasks to have their own distinct network presence, making them manageable as independent network endpoints. This is crucial for security, compliance, and complex network architectures where you need to control traffic flow to and from individual services with precision.
When using awsvpc mode with EC2 launch type, ECS attaches an ENI to the EC2 instance, and then assigns that ENI to your task. The task then gets an IP address from the subnet associated with that ENI. This is different from Fargate where ECS directly provisions the ENI for the task.
Understanding the relationship between task ENIs and AWS networking primitives is key. When you use awsvpc mode, you’re not just configuring a container; you’re configuring how a network interface, a public or private IP address, and associated security groups will be provisioned and managed for that specific task. You can even associate multiple ENIs with a single task if your workload requires it, providing more network flexibility.
The next hurdle you’ll face is understanding how to manage network traffic effectively using Network Load Balancers (NLBs) and Application Load Balancers (ALBs) with awsvpc mode, particularly when dealing with dynamic task IP addresses.