Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 30 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save jonashaag/4c01174c92ac71986e3dcc44cec6ad9c to your computer and use it in GitHub Desktop.
Save jonashaag/4c01174c92ac71986e3dcc44cec6ad9c to your computer and use it in GitHub Desktop.
AWS Fargate Docker Application Load Balancer Howto (without public IP)

AWS Fargate Docker Simple Deployment Setup with SSL termination

How to:

  • create a Docker-based AWS Fargate/ECS deployment
  • without the Docker containers having a public IP
  • with an Application Load Balancer as reverse proxy / SSL termination proxy sitting in front of the containers

For Fargate/ECS to be able to access your Docker images hosted on ECR (or somewhere else) you'll have to allow outbound internet access to the Fargate subnets. Here's how you do it.

  1. Create a Fargate Cluster with a new VPC with 2 (or more) subnets.
  2. Make the 2 subnets created in step 1 private, add 2 new public-facing subnets and bridge them with NAT:
    • Create 2 new public-facing subnets in your VPC in the AZ of the subnets auto-created in step 1. For example, if in step 1 2 subnets 10.0.0.0/24 (us-east-1a) and 10.0.1.0/24 (us-east-1b) were created, create 2 new subnets 10.0.2.0/24 (us-east-1a) and 10.0.3.0/24 (us-east-1b).
    • Create a NAT gateway in each of the new public-facing subnets (new EIP for each gateway).
    • Create a new route table for each of the new subnets and add two entries to each table: 10.0.0.0/16 -> local and 0.0.0.0/0 -> igw-xxx (the internet gateway auto-created in step 1).
    • Modify the route tables of each of the subnets auto-created in step 1 as follows: change the target of the 0.0.0.0/0 route to the nat-xxx NAT gateway of the subnet's AZ. In the example above, point
      • the 10.0.0.0/24 subnet's 0.0.0.0/0 route to the NAT gateway in subnet 10.0.2.0/24
      • the 10.0.1.0/24 subnet's 0.0.0.0/0 route to the NAT gateway in subnet 10.0.3.0/24.
    • You should now have
      • 2 new public-facing subnets routing 0.0.0.0/0 to an internet gateway
      • 2 private subnets routing 0.0.0.0/0 to a NAT gateway in the same AZ.
  3. Create an Application Load Balancer with the 2 new public-facing subnets selected in the "Availability Zones" section.
  4. Create ECR repository and upload your image:
    • Go to ECS, Repositories, Create Repository.
    • Upload your image and remember its tag.
  5. Create Fargate Task Definition(s) for your task(s):
    • Select Fargate type.
    • Select "ecsTaskExecutionRole" as Task Role.
    • Use "awsvpc" networking mode.
    • Press "Add container".
      • Put the URL of your new ECR repository plus the image tag.
      • Leave the "Healthcheck" fields empty unless you know what you're doing. Health checks will be done by the load balancer and will be configured in the next step.
  6. Create a Fargate Service:
    • Select Fargate type.
    • Choose your VPC created in step 1.
    • Select the 2 private subnets created in step 1.
    • Disable "Auto-assign public IP".
    • Choose "Application Load Balancer"
      • Select your load balancer created in step 3.
      • Add your container(s).
      • Choose health check options. Note that these are HTTP-based and different from the container health check options (not) used in step 5.
    • Service discovery is not required for this setup.
  7. Done!

Related material

@KijanaG
Copy link

KijanaG commented Apr 27, 2020

This is awesome! I've been looking for the best way to configure an ECS Fargate solution that is secure & scalable, and this is the greatest way so far! I've tried CloudFormation, ECS CLI, regular setup, but there aren't good enough resources with respect to tutorials on setting up secure Fargate Instances. I'm curious as to what the diagram would look like for the above set up. As you know there are many visual diagrams of different ways you can configure AWS architecture. Do you have any links to what this diagram would look like, or could you explain how to make one from this architecture? Also, how does the client access the application in this case? I tried to use the DNS name for the Load Balancer but that didn't seem to work. Thanks!

@jonashaag
Copy link
Author

PNG-Bild

Rough sketch. I hope everything is correct. Maybe you can turn this into a better diagram :)

@KijanaG
Copy link

KijanaG commented Apr 28, 2020

That’s awesome!! Thanks for the visual, I understand it much better now👌🏽

@ariel-frischer
Copy link

ariel-frischer commented Jul 13, 2020

@jonashaag Thanks for this awesome gist, I'm assuming that I also need to setup HTTPS port listener on my ALB with like route53 and CNAME? What should the listeners on the ALB look like?? I have them forwarding to target group of my ecs tasks. This does not seem to be working.

@jonashaag
Copy link
Author

Difficult to say with so little info. Try to get it to work with the default ALB DNS name, then add Route53.

@ariel-frischer
Copy link

Ok, seems like I finally got it working with ALB DNS, I will work on SSL with Route53 in meanwhile things should workout. Thanks again!

@ariel-frischer
Copy link

Update: It works! I added SSL port 443 to load balancer with target-group set to the correct ECS tasks. I just needed to add the correct container port to the inbound security group. I added A type record to my route 53 hosted zone set Alias (true) selected my load balancer (it's important to note this alias value prepended "dualstack" to the load balancer public dns). Using the prepended value I added a CNAME to my DNS registrar and viola works.

@jonashaag
Copy link
Author

jonashaag commented Jul 15, 2020

Congrats! AWS can be incredibly complex, without having a lot of benefits from the complexity (for the use cases I have encountered so far), which is why I try to not use it at all nowadays.

@ariel-frischer
Copy link

ariel-frischer commented Jul 15, 2020

Congrats! AWS can be incredibly complex, without having a lot of benefits from the complexity (for the use cases I have encountered so far), which is why I try to not use it at all nowadays.

I totally agree the complexity is a bit much at times but I haven't found that many cost efficient alternatives. Out of curiosity what have you been switching to heroku?

@jonashaag
Copy link
Author

Depending on the deployment complexity of the app I usually go with:

  • SSH + manual docker-compose for very simple apps
  • Heroku or self-hosted Dokku for simple apps
  • AWS/GCS with RDS/ElastiCache/etc. and Dokku for apps that require multiple databases and/or automatic backup etc.

@ariel-frischer
Copy link

That is insightful I'll definitely checkout Dokku thanks again!

@yogeshwar607
Copy link

@fmunirdev how u solved it ? i am also getting same error

@arnocornette
Copy link

@yogeshwar607 We added both the com.amazonaws.region.ecr.dkr and the com.amazonaws.region.ecr.api and the S3 gateway endpoint?

In the VPC > Endpoints screen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment