LoginSignup
8
8

More than 5 years have passed since last update.

TerraformでECR上のDockerイメージをEC2にささっとデプロイ

Posted at

やったこと

ちょっとしたWebアプリをAWSに気軽にデプロイできるようにしたかったので、Terraformを使ってECRのDockerイメージをEC2にささっとデプロイしてみたメモ。

ちょっとしたものを気軽にデプロイしたいだけなので、以下のようなかなり手抜きな内容です。

  • VPCを適当に構築
  • IAMロールでEC2からECRへのアクセスを許可
  • 80番ポートのみアクセスを許可したEC2を起動
  • User DataでDockerのインストールからECR上のコンテナのデプロイまで実施

作ったもの

  • シェルスクリプト
    • userdata.sh
  • Terraformのテンプレート
    • main.tf
    • variables.tf
    • outputs.tf

各種ファイルの内容

userdata.sh

Dockerのインストールと指定したイメージの起動を行います。
IMAGE_NAMEの部分は適宜修正します。

userdata.sh
#!/bin/bash -eux

IMAGE_NAME=xxx.dkr.ecr.ap-northeast-1.amazonaws.com/my-nginx

sudo yum install -y docker
sudo systemctl enable docker
sudo systemctl start docker

aws ecr get-login --no-include-email --region ap-northeast-1 | sudo sh
sudo docker run -d -p 80:80 $IMAGE_NAME

BASE64にエンコードして、あとでmain.tfに貼り付けます。

$ cat userdata.sh | base64
IyEvYmluL2Jhc2ggLWV1eAoKSU1BR0VfTkFNRT14eHguZGtyLmVjci5hcC1ub3J0aGVhc3QtMS5hbWF6b25hd3MuY29tL215LW5naW54CgpzdWRvIHl1bSBpbnN0YWxsIC15IGRvY2tlcgpzdWRvIHN5c3RlbWN0bCBlbmFibGUgZG9ja2VyCnN1ZG8gc3lzdGVtY3RsIHN0YXJ0IGRvY2tlcgoKYXdzIGVjciBnZXQtbG9naW4gLS1uby1pbmNsdWRlLWVtYWlsIC0tcmVnaW9uIGFwLW5vcnRoZWFzdC0xIHwgc3VkbyBzaApzdWRvIGRvY2tlciBydW4gLWQgLXAgODA6ODAgJElNQUdFX05BTUUK

main.tf

長いファイルなので、Provider、VPC、IAM、EC2に分けて掲載します。
全体的にBasic Two-Tier AWS Architectureを参考にしています。

Provider

# ######## #
# Provider #
# ######## #

provider "aws" {
  version = "~> 1.3"
  region = "${var.aws_region}"
}

VPC

# ### #
# VPC #
# ### #

resource "aws_vpc" "default" {
  cidr_block = "10.0.0.0/16"
}

resource "aws_internet_gateway" "default" {
  vpc_id = "${aws_vpc.default.id}"
}

resource "aws_route" "internet_access" {
  route_table_id         = "${aws_vpc.default.main_route_table_id}"
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = "${aws_internet_gateway.default.id}"
}

resource "aws_subnet" "default" {
  vpc_id                  = "${aws_vpc.default.id}"
  cidr_block              = "10.0.0.0/24"
  map_public_ip_on_launch = true
}

IAM

# ### #
# IAM #
# ### #

resource "aws_iam_role" "instance_role" {
    name = "instance_role"
    assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
}

resource "aws_iam_policy_attachment" "ecs-role-attach" {
    name = "ecs-role-attach"
    roles = ["${aws_iam_role.instance_role.name}"]
    policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
}

resource "aws_iam_instance_profile" "instance_role" {
    name = "instance_role"
    role = "${aws_iam_role.instance_role.name}"
}

EC2へのIAMロールの割り当てについては、以下を参考にしました。

EC2

# ### #
# EC2 #
# ### #

resource "aws_security_group" "default" {
  description = "Used in the terraform"
  vpc_id      = "${aws_vpc.default.id}"

  ingress {
    from_port   = 80
    to_port     = 80
    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"]
  }
}

resource "aws_instance" "instance" {
  instance_type = "t2.micro"
  ami = "${lookup(var.aws_amis, var.aws_region)}"

  vpc_security_group_ids = ["${aws_security_group.default.id}"]
  subnet_id = "${aws_subnet.default.id}"

  iam_instance_profile = "instance_role"

  user_data = "IyEvYmluL2Jhc2ggLWV1eAoKSU1BR0VfTkFNRT14eHguZGtyLmVjci5hcC1ub3J0aGVhc3QtMS5hbWF6b25hd3MuY29tL215LW5naW54CgpzdWRvIHl1bSBpbnN0YWxsIC15IGRvY2tlcgpzdWRvIHN5c3RlbWN0bCBlbmFibGUgZG9ja2VyCnN1ZG8gc3lzdGVtY3RsIHN0YXJ0IGRvY2tlcgoKYXdzIGVjciBnZXQtbG9naW4gLS1uby1pbmNsdWRlLWVtYWlsIC0tcmVnaW9uIGFwLW5vcnRoZWFzdC0xIHwgc3VkbyBzaApzdWRvIGRvY2tlciBydW4gLWQgLXAgODA6ODAgJElNQUdFX05BTUUK"
}

user_dataには、先ほどBase64でエンコードしたものを貼り付けています。

variables.tf

# ####### #
# Overall #
# ####### #

variable "aws_region" {
  description = "AWS region to launch servers."
  default     = "ap-northeast-1"
}

# ### #
# EC2 #
# ### #

# Amazon Linux 2
variable "aws_amis" {
  default = {
    us-east-1      = "ami-b70554c8"
    ap-northeast-1 = "ami-e99f4896"
  }
}

outputs.tf

output "address" {
  value = "http://${aws_instance.instance.public_ip}"
}

実行

$ terraform init
    :
    :
    :
$ terraform apply
    :
    :
    :
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

Outputs:

address = http://xxx.xxx.xxx.xxx

Outputsに表示されているURLにアクセスすると、無事Nginxのページが表示されました。

スクリーンショット 2018-08-17 17.54.02.png

片付け

terraform destroy
8
8
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
8
8