Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retrieve the public IP address of an AWS ECS contrainer using Terraform

How do I pull the public IP address assigned to a container of an AWS ECS cluster/service?

For testing purposes I do not want to spin up an ALB, so I just added service to a public subnet. The best I was able to come up with so far is to use aws cli to pull the IP address. I am wondering if there's a way to pull this somehow using Terraform attributes.

resource "aws_ecs_cluster" "this" {
  name = "${lower(var.app_name)}-${lower(var.app_environment)}-cluster"
  
}

resource "aws_ecs_task_definition" "this" {
  family                   = "${lower(var.app_name)}-${lower(var.app_environment)}-task"
  execution_role_arn       = aws_iam_role.ecs_task_execution_role.arn
  container_definitions    = jsonencode([{
    name            = "${lower(var.app_name)}-${lower(var.app_environment)}-container"
    image           = "nginx:latest"
    portMappings    = [{ containerPort = 80 }]
  }])
  memory                   = 3072
  cpu                      = 1024
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"

  runtime_platform {
    operating_system_family = "LINUX"
    cpu_architecture        = "X86_64"
  }
}

resource "aws_ecs_service" "this" {
  name            = "${lower(var.app_name)}-${lower(var.app_environment)}-service"
  cluster         = aws_ecs_cluster.this.id
  task_definition = aws_ecs_task_definition.this.arn
  desired_count   = 1

  # Assign an Elastic IP address to the task
  network_configuration {
    assign_public_ip = true
    subnets          = [module.vpc100.public_subnet1_id,module.vpc100.public_subnet2_id]
    security_groups  = [aws_security_group.this.id]
  }

  # Configure the service to use Fargate
  launch_type = "FARGATE"

  tags = {
    Name = "${lower(var.app_name)}-${lower(var.app_environment)}-container"
  }

}

# My hack to pull the public IP address
resource "terraform_data" "publicip" {
  provisioner "local-exec" {
    command = <<EOF
        clustername=${lower(var.app_name)}-${lower(var.app_environment)}-cluster
        taskid=$(aws ecs list-tasks --cluster $clustername --query "taskArns[0]" --output text)
        eni=$(aws ecs describe-tasks --tasks $taskid --cluster example6-dev-cluster --query "tasks[0].attachments[0].details[?name=='networkInterfaceId'].value" --output text)
        publicip=$(aws ec2 describe-network-interfaces --query "NetworkInterfaces[?NetworkInterfaceId=='$eni'].Association.PublicIp" --output text)
        echo "$publicip"
    EOF
  }
  depends_on = [
    aws_ecs_service.this
  ]
}
like image 315
ucipass Avatar asked Sep 03 '25 13:09

ucipass


2 Answers

You can retrieve the public IP address assigned to a container in an AWS ECS cluster/service by following these steps:

  1. Set enable_ecs_managed_tags to true in your aws_ecs_service. This configures ECS to tag the network interface with essential information:

aws:ecs:serviceName = <aws_ecs_service.yourservice.name>

aws:ecs:clusterName = <aws_ecs_service.yourservice.cluster>

resource "aws_ecs_service" "this" {
  # Your other configuration goes here
  task_definition         = aws_ecs_task_definition.this.arn
  desired_count           = 1

  enable_ecs_managed_tags = true  # It will tag the network interface with service name
  wait_for_steady_state   = true  # Terraform will wait for the service to reach a steady state 

  # Assign an Elastic IP address to the task
  network_configuration {
  # Rest of the configuration goes here
}
  1. Use tag filter to identify the network interface
data "aws_network_interface" "interface_tags" {
  filter {
    name   = "tag:aws:ecs:serviceName"
    values = ["${lower(var.app_name)}-${lower(var.app_environment)}-service"]
  }
}

output "public_ip" {
    value = data.aws_network_interface.interface_tags.association[0].public_ip
}

For further context, you can refer to the GitHub issue How can I access IP from aws_ecs_service using assign_public_ip

like image 60
Mohit Khandelwal Avatar answered Sep 05 '25 02:09

Mohit Khandelwal


You can't do that with Terraform. Terraform just knows that it told AWS to create a service. It doesn't know anything about any current tasks that are being managed by the service. You'll need to run something like an AWS CLI command after your terraform apply is complete.

like image 45
Mark B Avatar answered Sep 05 '25 04:09

Mark B