Your PC can't even




AWS - ECS Windows Containers

This article demonstrates how to run windows containers in AWS with dynamic port mapping.

How is this useful?

  • Containerizing applicaitons provides sufficient insulation between each environment. In certain instances, you may choose to not refactor .Net framework applications to run in fargate. Consequentially, you would run these on a EC2 cluster inside ECS. Layering in dynamic port mapping allows AWS to manage which port a container exposes, and how to route traffic to it from an application load balancer. This is useful as you can now host webservices using default ports 80/443 and not have to specify the port after your url.

Create a new cluster in ECS

  • Navigate to ECS and click "Create Cluster"

  • Select Template "EC2 Windows + Networking"

  • Configure your EC2, this step is fairly straight forward if you are familar with EC2. Name your instance, select on demand or spot, the EC2 type, AMI, EBS size, SSH access (I opted for none), and the VPC. The major point that I will call attention to is the ECS role. If you already have one available, you can select it. Otherwise, have AWS create you a new role that will be used throught the process.

Create some security groups

  • There are two security groups that need to be made. The first handles traffic to the application load balancer, and the second handles traffic to the container instance we just made.

    First, create a group with a name indicating traffic coming into your alb. Something like "container-alb-secg" works. You can also use tags if you prefer. Configure it with the following rules:

    container-alb-secg => Inbound Rules:

    Type Protocl Port Range Source Description
    HTTP TCP 80 0.0.0.0/0 All traffic on port 80
    HTTP TCP 80 ::/0 All traffic on port 80
    HTTPS TCP 443 0.0.0.0/0 All traffic on port 443
    HTTPS TCP 443 ::/0 All traffic on port 443

    container-alb-secg => Outbound Rules:

    Type Protocl Port Range Source Description
    All Traffic All All 0.0.0.0/0 All traffic

    Second, create a group with a name indicating traffic coming from your alb to your container instance. Something like "ecs-container-config" works.

    ecs-container-config => Inbound Rules:

    Type Protocl Port Range Source Description
    HTTP TCP 80 0.0.0.0/0 All traffic on port 80. Specifically, this is needed for the ECR agent to manage images on your instance.
    HTTP TCP 80 ::/0 All traffic on port 80. Specifically, this is needed for the ECR agent to manage images on your instance.
    All traffic All ALL sg-YOUR_IDENTIFIER / container-alb-secg All traffic from anything that has this security group.

    ecs-container-config => Outbound Rules:

    Type Protocl Port Range Source Description
    All Traffic All All 0.0.0.0/0 All traffic

Target Groups

  • Create a target group. The target group will be attached to the application load balancer we will make later. We will be using SSL termination, so setting this up on port 80 is fine.

    From EC2 > Sidebar > Load Balancing > Target Groups

    Create Target Group. Configre as target type "instance", give it a name, Protocol HTTP on Port 80, Select your VPC, Protocl version as HTTP1, click Next.

    Next, you will want to configure your health check settings. This is important in order to keep your instance healthy. If it returns a success code outside of your range, it will consider the current group unhealthy. This in turn will drain the port and remove the target. The path you use should be relative to the host header, something like this will do.

    On the final page prior to creating the target group, it is important TO NOT register any instance. We want this to interact with the balancer, not a specific instance.


    While not relevant to this example, you have access to additional attributes. If in the future you plan to load balance against multiple containers or multiple containers on multiple clusters, Load Balancing Algorithm would be relevant.

Creating the application load balancer

  • Create a new application load balancer. Attach a cert from ACM and create a listener for port 443. This will route traffic to our target group. We will be using SSL termination, setting up the listener on 443 will encrypt traffic to our container listening on port 80.

    From EC2 > Sidebar > Load Balancing > Load Balancers > Create Load Balancer

    Add the security group we created eariler "container-alb-secg" and configure attributes.

    Add rules to your listener, in general you need at least two. One is the default for when no others match, this can route to what you want.The other rule is based on the host header and routes traffic to the target group we created. As you add more services to your cluster, you will need to create more groups and add more rules to this balancer.

Create a task definition in ECS

  • Create a new launch type of EC2. Give a name to the task, and skip everything until you get to Container Definition. Once at the container definition, add the path to your ECR image with the target tag, give it a name, allocate some memory and CPU (note for windows containers on EC2, this provisioning will always slice off that chunk for the container and not share it with others so be careful).

    For port mapping, assign a host port 0 (this will be dynamically mapped through the ALB => target group) and a container port of 80 (because we're terminating SSL at the balancer)

Create a service using the task definition in ECS

  • Navigate to your cluster under the Services tab and click Create.

    Configure the basic configuration with your task definition, cluster, name, service type (replica), number of tasks (guarantees this many tasks will run), Min healthy percent (0 as we don't require minumum running tasks 100 for prod), and max (200 for 2 running tasks).

    Configure the Deployment as rolling (picks up your latest ECR image with matching tag) and the task placement as even.

    On the next page configure your load balancing as "application load balancer", select your ECS role from earlier, and the load balancer you made.

    Select the Container name / port from the task definition from earlier and add it to the balancer.

    Select the target group you made earlier and the rest should fill in automatically.

    Do not configure service discovery, you can route traffic through Route53 instead. Follow the next steps with default configuration after.

    Your service should have created a task and the target group should have an entity with a dynamically registered port!


All that's left is to route traffic to your ALB with route53.