0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Terraform個人メモ:ローカルで作成したGoアプリケーションを、Terraformテンプレートを使用してECRからECSへ自動デプロイ

Last updated at Posted at 2025-01-22

はじめに

この記事では、ローカルで作成したGoアプリケーションをTerraformを用いてインフラをコード化し、ECSがECRからDockerイメージを自動的にプルして本番環境にデプロイする手順を紹介します。

この記事は、過去の技術検証内容を組み合わせた実践的な応用例です。

自分用の備忘録も兼ねて、手順や実施内容を詳しくまとめていきます。少しでも参考になれば幸いです。

補足:過去記事の組み合わせによる検証

※注意点
本記事では、以下の記事で取り上げた技術検証を組み合わせて進めています。

1. Go言語用のDockerfileをシェルスクリプトで一括作成する方法👇

2. Dockerfileをローカルで実行し、ブラウザから『Hello, World!』を表示する方法👇

3. DockerイメージをAWS CLIを使ってECRにプッシュする方法👇

Terraformテンプレートの準備

以下は、今回使用したTerraformテンプレートです。このテンプレートには、ECSクラスター、タスク定義、IAMロールなど、必要なリソース設定が含まれています。

注意点として、デプロイするアプリケーションは「ポート1323」で動作するため、containerPort を正しく指定する必要があります。

main.tf
# AWSプロバイダーの設定
provider "aws" {
  region = "ap-northeast-1"
}

# VPCの作成
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "honda-vpc"
  }
}

# パブリックサブネットの作成
resource "aws_subnet" "public1" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.0.0/20"
  availability_zone = "ap-northeast-1a"

  tags = {
    Name = "honda-subnet-public1-ap-northeast-1a"
  }
}

# インターネットゲートウェイの作成
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "honda-igw"
  }
}

# パブリックルートテーブルの作成
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "honda-rtb-public"
  }
}

# パブリックルートの設定
resource "aws_route" "public_route" {
  route_table_id         = aws_route_table.public.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.main.id
}

# サブネットとルートテーブルの関連付け
resource "aws_route_table_association" "public_subnet_association" {
  subnet_id      = aws_subnet.public1.id
  route_table_id = aws_route_table.public.id
}

# セキュリティグループの作成(ECS用)
resource "aws_security_group" "ecs_sg" {
  vpc_id = aws_vpc.main.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 1323
    to_port     = 1323
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "ecs-sg"
  }
}

# ECSクラスターの作成
resource "aws_ecs_cluster" "main" {
  name = "my-ecs-cluster"
}

# ECSタスク実行ロールの作成
resource "aws_iam_role" "ecs_task_execution_role" {
  name = "ecs-task-execution-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "ecs-tasks.amazonaws.com" }
      Action    = "sts:AssumeRole"
    }]
  })

  inline_policy {
    name = "ecs-task-execution-policy"
    policy = jsonencode({
      Version = "2012-10-17"
      Statement = [
        {
          Effect   = "Allow"
          Action   = [
            "ecr:GetAuthorizationToken",
            "ecr:GetDownloadUrlForLayer",
            "ecr:BatchGetImage",
            "logs:CreateLogStream",
            "logs:PutLogEvents",
            "s3:GetObject"
          ]
          Resource = "*"
        }
      ]
    })
  }
}

# ECSタスク定義の作成
resource "aws_ecs_task_definition" "main" {
  family                   = "my-app-task"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = "256"
  memory                   = "512"
  execution_role_arn       = aws_iam_role.ecs_task_execution_role.arn

  container_definitions = jsonencode([
    {
      name       = "my-app-repo"
      image      = "xxx.dkr.ecr.ap-northeast-1.amazonaws.com/my-app-repo"
      portMappings = [
        {
          containerPort = 1323
          hostPort      = 1323
          protocol      = "tcp"
        }
      ]
    }
  ])
}

# ECSサービスの作成
resource "aws_ecs_service" "main" {
  name            = "my-ecs-service"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.main.arn
  desired_count   = 1
  launch_type     = "FARGATE"

  network_configuration {
    subnets         = [aws_subnet.public1.id]
    security_groups = [aws_security_group.ecs_sg.id]
    assign_public_ip = true
  }
}

今回は、過去の記事で作成したテンプレートを基に、コンテナとホストのポート設定、およびセキュリティグループ周りの設定を修正しました。

実際に動かしてみた

ここでは詳細な使い方は省略しますが、私はCloudShellを使ってTerraformを実行しています。

詳しく知りたい方は、過去の記事で紹介していますので、ぜひ参考にしてみてください。

デプロイ後の動作確認

デプロイが完了したら、タスクが正常に実行されていることを確認します。ここでは、ECRのイメージコンテナからプルされていることも合わせて確認しました。

スクリーンショット 2024-12-08 12.16.37.png

ECSページの「クラスター」→「タスク」タブから、実行中のタスクを選択し、タスクのパブリックIPを確認します。

http://52.195.176.91:1323/

ここで、タスクが使用しているパブリックIP(例:52.195.176.91)を確認したら、ブラウザでアクセスしてみます。

Screenshot 2025-01-21 at 14.35.02.png

想定通り、Goアプリが正常に動作し、Hello, World! と表示されることを確認できました!

まとめ

ここまでお読みいただき、ありがとうございました。今回の記事は、過去の複雑な技術検証を組み合わせた内容となりましたが、無事にまとめることができて本当によかったです。

ただ、CloudFormationで同じことをしていた経験があったため、その知識を活用して比較的スムーズに進めることができました。

この記事がどなたかの技術的な参考になれば幸いです!

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?