IP Public on AWS ECS Fargate

There are many cases that might you need to have direct IP public address on your ECS task. When your tasks are on EC2, situation is a little easier, but if you are on Fargate, you need to do some tricks to get a reachable IP public.

Before checking the script, don’t forget to consider these facts:

  • For getting a reachable public IP on task, you need to run the cluster on public subnet.

  • If you are in a subnet that is connected to NAT gateway, your task would not be reachable.

  • If you need to just get your NAT IP, you can take it easy and just run commands like this in your entry point scripts: NAT_PUBLIC_IP=$(curl checkip.amazonaws.com)

  • If your app inside container, doesn’t need to know its public IP, so you are good, you don’t need to any special thing. Only enable Auto-assign public IP in your cluster service settings or in CDK.

In my case, that container is running a SIP application server, it needs to know its public interface to use in outbound SIP messages. So, I added below scripts as my container entry point, and then use the public IP value in app settings and the starting up the process.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash

# Install the ca-certificates package
apt-get update
apt-get install -y ca-certificates

# Update the root certificates
update-ca-certificates --fresh

# Install the AWS CLI version 2 using apt-get
apt-get install -y unzip curl less jq
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
./aws/install

task_metadata=$(curl -s $ECS_CONTAINER_METADATA_URI_V4/task)
cluster_name=$(echo $task_metadata | jq -r '.TaskARN' | cut -d/ -f2)
echo $cluster_name

task_id=$(echo $task_metadata | jq -r '.TaskARN' | cut -d/ -f3)
echo $task_id

eni_id=$(aws ecs describe-tasks --cluster $cluster_name --tasks $task_id --query 'tasks[0].attachments[0].details[?name==`networkInterfaceId`].value' --output text)
public_ip=$(aws ec2 describe-network-interfaces --network-interface-ids "$eni_id" --query 'NetworkInterfaces[0].Association.PublicIp' --output text)

echo "PUBLIC_IP: $public_ip"

if you installed some of the packages in building image, so you don’t need install again. Just install aws-cli. Then we get task eni-id and with ec2 describe-network-interfaces we get IP public address that is assigned by AWS to task ENI.

Don’t forget that you need the specific role for running ec2 describe-network-interfaces. Then add below in your task IAM role:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeNetworkInterfaces"
            ],
            "Resource": "*"
        }
    ]
}
updatedupdated2023-02-172023-02-17