ECS Fargate Docker container securely hosted behind API Gateway using Terraform

Chetan Patel
5 min readJan 13, 2022

There are often occasions where I need to do a rapid POC and spin up a Docker container to demo and experiment with some type of service. Normally this is easy to do as you can just run the container on a local host but what if you want to demo this to senior management or to engineers or even share around outside of your secure private network? there are many occasion when this type scenario can be necessary and even helpful in getting a project going so i’m going to show you a method where you can do this with a certain amount of security layering attached to it. The main benefit in this architecture is that there is no Application Load Balancer needed or Nat Gateway(with limitations) to incur costs for.

First lets list what this terraform template produces:
1) A single ECS container using ECS Fargate orchestration tooling
2) The container runs in a private subnet so is secure by design to the outside world. The only access to it is through API Gateway and a VPC Link.
3) Service discovery namespace. A private DNS namespace which the ECS Fargate task ENI is registered against. This allows routes and DNS discovery for API Gateway front end to use.
4) VPC endpoints in the private subnet. This allows the Fargate task to talk to any supported AWS services in a private network. For my requirements I need Cloudwatch, ECR, S3 but you could do this with any AWS service which supports it(which is more then 99%)
5) HTTP Api Gateway service with relevant paths/routes.
6) Private VPC link. This can be confusing as the term is very similar to VPC Endpoint and under the hood it probably works the same but its an aliasing type of method which allows routes from API Gateway DNS name to an AWS resource like Service Discovery or ALB DNS name.
6) Route 53 public DNS entry which allows you to alias your own controlled domain name to the API Gateway invoking url. ie www.thisismysite.mysite.com. This is a nice touch as it allows you to hide the API gateway url and put your own url in front of it.
7) An ssl cert attachment to to the newly created public DNS entry to secure data in transit.
8) This terraform template creates an empty ECR registry. You need to push your docker image their after you standup your infrastructure.
9) Optionally you easily add an AWS WAF with web ACL to the API Gateway endpoint to add an additional layer of security. I haven’t included it in this Terraform template but its easy enough to do should you require.

Limitations
Its important to list out the limitation of this and what it ‘doesn’t’ do:
1. The container runs in a private subnet without any access to the internet. The only access granted is to private VPC endpoints which traverse the AWS network for services, so if your container needs access to the outside world you’d need to put in a NAT gateway.
2. This method is best suited to API based containers as its hosted behind API Gateway and supports simple HTTP methods. This will not support something like we website running on nginx.
3. Persistent storage isn’t included in this setup. You can easily add an EFS mount volume to the task if you service requires shared or persistent data to work.
4. There is some basic logging setup with this which sends log data to Cloudwatch. This is no observability metrics setup on this architecture.

Prerequisites
Listed in the GitHub Repo aswell but you should have some understanding of AWS roles, permissions and services. Some high level knowledge of Docker is advisable.

  1. Valid SSL certificate ARN matching on the domain name alias which you intend to use ie “sidecar.mywebsite.com”.
  2. Docker image locally to push to newly created ECS. This containers serves 3 api endpoints(metrics, health and metrics/health), you should change your terraform integrations to match your own container requirements
  3. VPC with at least 2 private subnets and DNS hostnames and DNS Resolution activated.
  4. Existing domain name registered in route53 eg “mywebsite.com”
  5. Terraform must be bootstrapped. This means that a state S3 bucket and a state locking DynamoDB table must be initialised.

GitHub repo
https://github.com/chelto/ApiGateway-Fargate-Terraform-templates

Resources created
API Gateway HTTP protocol. With 3 integrations routes, Metrics, Health and metrics/prometheus

  • Custom Domain name for API gateway
  • VPC Link for API
  • Service discovery for ECS
  • ECR Repo
  • ECS Cluster
  • VPC Endpoints
  • IAM Policies and roles
  • Fargate Task Definition
  • Route 53 record with alias to API Gateway VPClink
  • Security groups

Anomalies
You’ll notice that there are 4 VPC endpoints created for this architecture. Cloudwatch and ECR are self explanatory but the S3 and DKR ones need some elaboration.
S3, when Fargate service pulls a docker image from ECR it first needs to save it to an AWS owned s3 bucket hence a VPC endpoint for S3. I had had the error “”CannotPullContainerError: API error” in Amazon ECS” which was unhelpful. Struggling with this for days I eventually found out about the s3 bucket buried in some AWS documentation.
DKR, another quirk which means that Fargate service needs to run Docker commands to pull private images and to do this the service needs access to “com.amazonaws.region.ecr.dkr” api.
Link to AWS official
https://docs.aws.amazon.com/AmazonECR/latest/userguide/vpc-endpoints.html

API Gateway
In my example my Docker container is an experimental API with 4 GET path urls which return a response. Mapping with over to API Gateway is a standard process using the 3 paths:

A full list of post launch commands and variables are listed in the Git repo to stand this service up.
You can customise the template according to your specific needs but I hope this gives you a view of what I came up with to run a barebones secure Docker container which doesn’t have cost of a NAT and ALB.

--

--

Chetan Patel

Mainly came to the tech game with cloud computing. Interested in serverless and event driven architecture and services.