1.AWSアカウントIDの設定
アカウントIDを環境変数に保存し、後の操作で使用できるようにします。
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
2.IAM関連
ECSタスクがCloudWatchなどの他のAWSサービスにアクセスするためのロールを作成します。
cat << EOF > trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
aws iam create-role --role-name hello-world-rails-task-execution-role --assume-role-policy-document file://trust-policy.json
aws iam attach-role-policy --role-name hello-world-rails-task-execution-role --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
3.ECRリポジトリの作成とDockerイメージのプッシュ
Dockerイメージを保存するリポジトリをECRで作成し、Railsアプリのイメージをビルドしてプッシュします。
リポジトリの作成
aws ecr create-repository --repository-name hello-world-rails-repo
Dockerイメージのビルドとプッシュ(ローカル)
export ACCOUNT_ID=<aws_account_id>
docker buildx build --platform linux/amd64 -t hello-world-rails:latest .
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com
docker tag hello-world-rails:latest ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-rails-repo:latest
docker push ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-rails-repo:latest
4.ネットワーク設定
VPC、サブネット、インターネットゲートウェイ、ルートテーブルなどのネットワーク構成を設定します。
VPCの作成
aws ec2 create-vpc --cidr-block 10.0.0.0/16 --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=hello-world-rails-vpc}]'
export VPC_ID=$(aws ec2 describe-vpcs --filters "Name=tag:Name,Values=hello-world-rails-vpc" --query "Vpcs[0].VpcId" --output text)
サブネットの作成
aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block 10.0.1.0/24 --availability-zone ap-northeast-1a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=hello-world-rails-public-subnet-1}]'
aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block 10.0.2.0/24 --availability-zone ap-northeast-1c \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=hello-world-rails-public-subnet-2}]'
export SUBNET_ID_1=$(aws ec2 describe-subnets --filters "Name=tag:Name,Values=hello-world-rails-public-subnet-1" --query "Subnets[0].SubnetId" --output text)
export SUBNET_ID_2=$(aws ec2 describe-subnets --filters "Name=tag:Name,Values=hello-world-rails-public-subnet-2" --query "Subnets[0].SubnetId" --output text)
サブネットのパブリックIP自動割り当ての設定
aws ec2 modify-subnet-attribute --subnet-id ${SUBNET_ID_1} --map-public-ip-on-launch
aws ec2 modify-subnet-attribute --subnet-id ${SUBNET_ID_2} --map-public-ip-on-launch
インターネットゲートウェイの作成とアタッチ
aws ec2 create-internet-gateway --tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=hello-world-rails-igw}]'
export IGW_ID=$(aws ec2 describe-internet-gateways --filters "Name=tag:Name,Values=hello-world-rails-igw" --query "InternetGateways[0].InternetGatewayId" --output text)
aws ec2 attach-internet-gateway --vpc-id $VPC_ID --internet-gateway-id $IGW_ID
ルートテーブルの作成とサブネットへの関連付け
aws ec2 create-route-table --vpc-id $VPC_ID --tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=hello-world-rails-route-table}]'
export ROUTE_TABLE_ID=$(aws ec2 describe-route-tables --filters "Name=tag:Name,Values=hello-world-rails-route-table" --query "RouteTables[0].RouteTableId" --output text)
aws ec2 create-route --route-table-id $ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW_ID
aws ec2 associate-route-table --route-table-id $ROUTE_TABLE_ID --subnet-id $SUBNET_ID_1
aws ec2 associate-route-table --route-table-id $ROUTE_TABLE_ID --subnet-id $SUBNET_ID_2
5.セキュリティグループの作成
ALBとECSタスクに必要なセキュリティグループを作成し、各種アクセスを設定します。
ALB用セキュリティグループ
aws ec2 create-security-group --group-name hello-world-rails-alb-sg \
--description "ALB security group" --vpc-id $VPC_ID
export ALB_SG_ID=$(aws ec2 describe-security-groups --filters "Name=group-name,Values=hello-world-rails-alb-sg" --query "SecurityGroups[0].GroupId" --output text)
aws ec2 authorize-security-group-ingress --group-id $ALB_SG_ID \
--protocol tcp --port 80 --cidr 0.0.0.0/0
ECSタスク用セキュリティグループ
aws ec2 create-security-group --group-name hello-world-rails-ecs-sg \
--description "ECS task security group" --vpc-id $VPC_ID
export ECS_TASK_SG_ID=$(aws ec2 describe-security-groups --filters "Name=group-name,Values=hello-world-rails-ecs-sg" --query "SecurityGroups[0].GroupId" --output text)
aws ec2 authorize-security-group-ingress --group-id $ECS_TASK_SG_ID \
--protocol tcp --port 3000 --source-group $ALB_SG_ID
6.ロードバランサー関連
ALBおよびターゲットグループを設定し、トラフィックのルーティング設定を行います。
ターゲットグループの作成
aws elbv2 create-target-group --name hello-world-rails-tg --protocol HTTP --port 3000 \
--vpc-id $VPC_ID --target-type ip
export TG_ARN=$(aws elbv2 describe-target-groups --names hello-world-rails-tg --query "TargetGroups[0].TargetGroupArn" --output text)
ALBの作成と設定
aws elbv2 create-load-balancer --name hello-world-rails-alb \
--subnets $SUBNET_ID_1 $SUBNET_ID_2 \
--security-groups $ALB_SG_ID \
--scheme internet-facing \
--type application \
--ip-address-type ipv4
export ALB_ARN=$(aws elbv2 describe-load-balancers --names hello-world-rails-alb --query "LoadBalancers[0].LoadBalancerArn" --output text)
ALBリスナーの作成
aws elbv2 create-listener --load-balancer-arn $ALB_ARN \
--protocol HTTP --port 80 \
--default-actions Type=forward,TargetGroupArn=$TG_ARN
7.ECSクラスターとタスク定義
クラスターを作成し、タスク定義を登録します。
ECSクラスターの作成
aws ecs create-cluster --cluster-name hello-world-rails-cluster
ECSタスク定義の作成
aws ecs register-task-definition --family hello-world-rails-task \
--network-mode awsvpc --requires-compatibilities FARGATE \
--execution-role-arn arn:aws:iam::$ACCOUNT_ID:role/hello-world-rails-task-execution-role \
--cpu "256" --memory "512" \
--container-definitions '[{"name":"hello-world-rails-container","image":"'$ACCOUNT_ID'.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-rails-repo:latest","portMappings":[{"containerPort":3000,"protocol":"tcp"}]}]'
8.ECSサービスの作成
ECSサービスを作成し、ALBと連携してトラフィックの処理を管理します。
aws ecs create-service --cluster hello-world-rails-cluster --service-name hello-world-rails-service \
--task-definition hello-world-rails-task --desired-count 1 --launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=['$SUBNET_ID_1','$SUBNET_ID_2'],securityGroups=['$ECS_TASK_SG_ID'],assignPublicIp='ENABLED'}" \
--load-balancers "targetGroupArn=$TG_ARN,containerName=hello-world-rails-container,containerPort=3000"
9.CloudWatchロググループの作成
ECSタスクのログを保存するCloudWatchロググループを作成します。
aws logs create-log-group --log-group-name /ecs/hello-world-rails-task --region ap-northeast-1
10.ログの確認
CloudWatchログを使用して、ECSタスクが出力するログを確認する。
aws logs describe-log-streams --log-group-name /ecs/hello-world-rails-task
aws logs get-log-events --log-group-name /ecs/hello-world-rails-task --log-stream-name $LOG_STREAM_NAME --limit 50
11.ECS更新手順
ECSサービスにデプロイしたアプリケーションを更新する
docker buildx build --platform linux/amd64 -t hello-world-rails:latest .
docker tag hello-world-rails:latest $ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-rails-repo:latest
docker push $ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-rails-repo:latest
aws ecs update-service --cluster hello-world-rails-cluster --service hello-world-rails-service --task-definition hello-world-rails-task
12.全部削除する
1.ECSサービスの停止と削除
ECSサービスを停止して削除します。これにより、ECSタスクが停止され、ロードバランサーとの連携が解除されます。
サービスの停止
export SERVICE_NAME="hello-world-rails-service"
aws ecs update-service --cluster hello-world-rails-cluster \
--service $SERVICE_NAME --desired-count 0
サービスの削除
aws ecs delete-service --cluster hello-world-rails-cluster \
--service $SERVICE_NAME --force
2.ECSクラスターの削除
ECSクラスターを削除します。クラスター削除前にすべてのサービスが停止されていることを確認してください。
aws ecs delete-cluster --cluster hello-world-rails-cluster
3.CloudWatchロググループの削除
ECSタスクで使用していたCloudWatchロググループを削除します。
aws logs delete-log-group --log-group-name /ecs/hello-world-rails-task
4.ECRリポジトリの削除
ECRにプッシュされているDockerイメージを含むリポジトリを削除します。削除には--force
オプションを使用して、リポジトリ内のイメージも同時に削除します。
aws ecr delete-repository --repository-name hello-world-rails-repo --force
5.IAMロールの削除
ECSタスクで使用したIAMロールを削除します。まず、ロールにアタッチされたポリシーをデタッチし、その後ロールを削除します。
ポリシーのデタッチ
aws iam detach-role-policy --role-name hello-world-rails-task-execution-role \
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
ロール削除
aws iam delete-role --role-name hello-world-rails-task-execution-role
6.セキュリティグループの削除
ECSタスクとALBに使用したセキュリティグループを削除します。まず、各セキュリティグループのIDを取得し、その後削除します。
セキュリティグループIDの取得
export ECS_TASK_SG_ID=$(aws ec2 describe-security-groups --filters "Name=group-name,Values=hello-world-rails-ecs-sg" --query "SecurityGroups[0].GroupId" --output text)
export ALB_SG_ID=$(aws ec2 describe-security-groups --filters "Name=group-name,Values=hello-world-rails-alb-sg" --query "SecurityGroups[0].GroupId" --output text)
セキュリティグループの削除
aws ec2 delete-security-group --group-id $ECS_TASK_SG_ID
aws ec2 delete-security-group --group-id $ALB_SG_ID
7.ルートテーブルの削除
VPCのルートテーブルを削除します。ルートテーブルを削除する前に、サブネットからの関連付けを解除する必要があります。
ルートテーブルIDの取得
export ROUTE_TABLE_ID=$(aws ec2 describe-route-tables --filters "Name=tag:Name,Values=hello-world-rails-route-table" --query "RouteTables[0].RouteTableId" --output text)
サブネットからルートテーブルの関連を解除
aws ec2 disassociate-route-table --association-id $(aws ec2 describe-route-tables --route-table-id $ROUTE_TABLE_ID --query "Associations[0].RouteTableAssociationId" --output text)
ルートテーブルの削除
aws ec2 delete-route-table --route-table-id $ROUTE_TABLE_ID
8.インターネットゲートウェイの削除
VPCにアタッチされているインターネットゲートウェイをデタッチしてから削除します。
インターネットゲートウェイIDの取得
export IGW_ID=$(aws ec2 describe-internet-gateways --filters "Name=attachment.vpc-id,Values=$VPC_ID" --query "InternetGateways[0].InternetGatewayId" --output text)
インターネットゲートウェイのデタッチ
aws ec2 detach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID
インターネットゲートウェイの削除
aws ec2 delete-internet-gateway --internet-gateway-id $IGW_ID
9.サブネットの削除
VPC内にあるすべてのサブネットを削除します。サブネットIDを配列に格納し、ループで各サブネットを削除します。
サブネットIDを配列に格納
export SUBNET_IDS=($(aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPC_ID" --query "Subnets[*].SubnetId" --output text))
各サブネットの削除
for SUBNET_ID in "${SUBNET_IDS[@]}"; do
aws ec2 delete-subnet --subnet-id $SUBNET_ID
done
10.VPCの削除
最後にVPCを削除します。これにより、ネットワーク設定の基盤も完全に削除されます。
aws ec2 delete-vpc --vpc-id $VPC_ID