Dockerized App Using ECS, ECR, and Fargate

View Code Deploy

This example, inspired by the Docker Getting Started Tutorial, builds, deploys, and runs a simple containerized application to a private container registry, and scales out five load balanced replicas, all in just a handful of lines of Node.js code, and leveraging modern and best-in-class AWS features.

To do this, we use Pulumi infrastructure as code to provision an Elastic Container Service (ECS) cluster, build our Dockerfile and deploy the resulting image to a private Elastic Container Registry (ECR) repository, and then create a scaled-out Fargate service behind an Elastic Application Load Balancer that allows traffic from the Internet on port 80. Because this example using AWS services directly, you can mix in other resources, like S3 buckets, RDS databases, and so on.

Prerequisites

Running the Example

After cloning this repo, cd into it and run these commands:

  1. Create a new stack, which is an isolated deployment target for this example:

    $ pulumi stack init dev
  2. Set your desired AWS region:

    $ pulumi config set aws:region us-east-1 # any valid AWS region will work
  3. Deploy everything with a single pulumi up command. This will show you a preview of changes first, which includes all of the required AWS resources (clusters, services, and the like). Don’t worry if it’s more than you expected – this is one of the benefits of Pulumi, it configures everything so that so you don’t need to!

    $ pulumi up

    After being prompted and selecting “yes”, your deployment will begin. It’ll complete in a few minutes:

    ``` Updating (dev):

     Type                                                        Name                        Status
    
    • pulumi:pulumi:Stack aws-ts-hello-fargate-dev created
    • ├─ awsx:x:ecs:Cluster cluster created
    • │ ├─ awsx:x:ec2:SecurityGroup cluster created
    • │ │ ├─ awsx:x:ec2:EgressSecurityGroupRule cluster-egress created
    • │ │ │ └─ aws:ec2:SecurityGroupRule cluster-egress created
    • │ │ ├─ awsx:x:ec2:IngressSecurityGroupRule cluster-ssh created
    • │ │ │ └─ aws:ec2:SecurityGroupRule cluster-ssh created
    • │ │ ├─ awsx:x:ec2:IngressSecurityGroupRule cluster-containers created
    • │ │ │ └─ aws:ec2:SecurityGroupRule cluster-containers created
    • │ │ └─ aws:ec2:SecurityGroup cluster created
    • │ └─ aws:ecs:Cluster cluster created
    • ├─ awsx:x:elasticloadbalancingv2:ApplicationLoadBalancer net-lb created
    • │ ├─ awsx:x:elasticloadbalancingv2:ApplicationTargetGroup web created
    • │ │ └─ aws:elasticloadbalancingv2:TargetGroup ca84d134 created
    • │ ├─ awsx:x:elasticloadbalancingv2:ApplicationListener web created
    • │ │ ├─ awsx:x:ec2:IngressSecurityGroupRule web-external-0-ingress created
    • │ │ │ └─ aws:ec2:SecurityGroupRule web-external-0-ingress created
    • │ │ └─ aws:elasticloadbalancingv2:Listener web created
    • │ └─ aws:elasticloadbalancingv2:LoadBalancer 218ffe37 created
    • ├─ awsx:x:ec2:Vpc default-vpc created
    • │ ├─ awsx:x:ec2:Subnet default-vpc-public-0 created
    • │ ├─ awsx:x:ec2:Subnet default-vpc-public-1 created > │ ├─ aws:ec2:Subnet default-vpc-public-0 read > │ └─ aws:ec2:Subnet default-vpc-public-1 read
    • ├─ awsx:x:ecs:FargateTaskDefinition app-svc created
    • │ ├─ aws:ecr:Repository app-img created
    • │ ├─ aws:cloudwatch:LogGroup app-svc created
    • │ ├─ aws:iam:Role app-svc-task created
    • │ ├─ aws:iam:Role app-svc-execution created
    • │ ├─ aws:ecr:LifecyclePolicy app-img created
    • │ ├─ aws:iam:RolePolicyAttachment app-svc-task-32be53a2 created
    • │ ├─ aws:iam:RolePolicyAttachment app-svc-task-fd1a00e5 created
    • │ ├─ aws:iam:RolePolicyAttachment app-svc-execution-9a42f520 created
    • │ └─ aws:ecs:TaskDefinition app-svc created
    • ├─ awsx:x:ecs:FargateService app-svc created
    • │ └─ aws:ecs:Service app-svc created > └─ aws:ec2:Vpc default-vpc read

    Outputs: url: “218ffe37-e8023b7-1429118690.us-east-1.elb.amazonaws.com”

    Resources: + 34 created

    Duration: 3m30s

    Permalink: https://app.pulumi.com/acmecorp/aws-ts-hello-fargate/dev/updates/1 ```

  4. At this point, your app is running! The URL was published so it’s easy to interact with:

    $ curl http://$(pulumi stack output url)
    <h3>Hello World!</h3>
    <b>Hostname:</b> ip-172-31-39-18.ec2.internal<br/>
    <b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>

For more details on how to enable Redis or advanced options, please see the instructions in the Docker Getting Started guide.

  1. Once you are done, you can destroy all of the resources, and the stack:

    $ pulumi destroy
    $ pulumi stack rm