0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RailsアプリをRDSと連携させてECSにデプロイする

Last updated at Posted at 2024-11-03

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-rdb-task-execution-role --assume-role-policy-document file://trust-policy.json
aws iam attach-role-policy --role-name hello-world-rails-rdb-task-execution-role --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

3.ネットワーク設定

VPC、サブネット、インターネットゲートウェイ、ルートテーブルなどのネットワーク構成を設定します。

VPCの作成

aws ec2 create-vpc --cidr-block 10.0.0.0/16 --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=hello-world-rails-rdb-vpc}]'
export VPC_ID=$(aws ec2 describe-vpcs --filters "Name=tag:Name,Values=hello-world-rails-rdb-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-rdb-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-rdb-public-subnet-2}]'

export SUBNET_ID_1=$(aws ec2 describe-subnets --filters "Name=tag:Name,Values=hello-world-rails-rdb-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-rdb-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-rdb-igw}]'
export IGW_ID=$(aws ec2 describe-internet-gateways --filters "Name=tag:Name,Values=hello-world-rails-rdb-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-rdb-route-table}]'
export ROUTE_TABLE_ID=$(aws ec2 describe-route-tables --filters "Name=tag:Name,Values=hello-world-rails-rdb-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

4.セキュリティグループの作成

ALBとECSタスクに必要なセキュリティグループを作成し、各種アクセスを設定します。

ALB用セキュリティグループ

aws ec2 create-security-group --group-name hello-world-rails-rdb-alb-sg \
  --description "ALB security group for HTTP access" --vpc-id $VPC_ID

export ALB_SG_ID=$(aws ec2 describe-security-groups --filters "Name=group-name,Values=hello-world-rails-rdb-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およびRDS用セキュリティグループ

aws ec2 create-security-group --group-name hello-world-rails-rdb-ecs-rds-sg \
  --description "ECS and RDS security group for ALB access" --vpc-id $VPC_ID

export ECS_RDS_SG_ID=$(aws ec2 describe-security-groups --filters "Name=group-name,Values=hello-world-rails-rdb-ecs-rds-sg" --query "SecurityGroups[0].GroupId" --output text)

aws ec2 authorize-security-group-ingress --group-id $ECS_RDS_SG_ID \
  --protocol tcp --port 3000 --source-group $ALB_SG_ID

aws ec2 authorize-security-group-ingress --group-id $ECS_RDS_SG_ID \
  --protocol tcp --port 3306 --source-group $ECS_RDS_SG_ID

5.RDSインスタンスの作成

サブネットグループの作成

上記の --db-subnet-group-name に使うため、サブネットグループを作成する必要があります。

aws rds create-db-subnet-group \
    --db-subnet-group-name hello-world-rails-rdb-subnet-group \
    --db-subnet-group-description "Subnet group for hello-world-rails-rdb" \
    --subnet-ids $SUBNET_ID_1 $SUBNET_ID_2

RDSインスタンスの生成

完了後にエンドポイント情報を記録します。(数分かかる)

aws rds create-db-instance \
    --db-instance-identifier hello-world-rails-rdb-db \
    --db-instance-class db.t3.micro \
    --engine mysql \
    --allocated-storage 20 \
    --vpc-security-group-ids $ECS_RDS_SG_ID \
    --db-subnet-group-name hello-world-rails-rdb-subnet-group \
    --master-username db_user \
    --master-user-password password123 \
    --backup-retention-period 7 \
    --no-multi-az \
    --storage-type gp2 \
    --publicly-accessible \
    --port 3306 \
    --db-name rails_db \
    --region ap-northeast-1

下記のコマンドで値が返ってきたら作成完了

aws rds describe-db-instances --db-instance-identifier hello-world-rails-rdb-db --query "DBInstances[0].Endpoint.Address" --output text

環境変数の設定

RDSインスタンスが作成されたら、CloudShellで以下のコマンドを実行して、データベース接続に必要な環境変数を設定します。

export RDS_HOSTNAME=$(aws rds describe-db-instances --db-instance-identifier hello-world-rails-rdb-db --query "DBInstances[0].Endpoint.Address" --output text)

export RDS_PORT=3306
export RDS_DB_NAME="rails_db"
export RDS_USERNAME="db_user"
export RDS_PASSWORD="password123"

6.Railsアプリのデータベース作成

config/database.ymlに以下の設定を追加し、RDSと接続できるようにします。環境変数を使用することで、デプロイ先の環境に応じた設定が可能です。

config/database.yml の設定例

production:
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: <%= ENV.fetch("RDS_USERNAME") %>
  password: <%= ENV.fetch("RDS_PASSWORD") %>
  host: <%= ENV.fetch("RDS_HOSTNAME") %>
  port: <%= ENV.fetch("RDS_PORT") %>
  database: <%= ENV.fetch("RDS_DB_NAME") %>

7.マイグレーションの実行

Railsアプリケーションのデータベースを作成し、テーブル構造をマイグレーションします。

RAILS_ENV=production rails db:create
RAILS_ENV=production rails db:migrate

8.ECRリポジトリの作成とDockerイメージのプッシュ

Dockerイメージを保存するリポジトリをECRで作成し、Railsアプリのイメージをビルドしてプッシュします。

リポジトリの作成

aws ecr create-repository --repository-name hello-world-rails-rdb-repo

Dockerイメージのビルドとプッシュ(ローカル)

export ACCOUNT_ID=<aws_account_id>
docker buildx build --platform linux/amd64 -t hello-world-rails-rdb: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-rdb:latest ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-rails-rdb-repo:latest
docker push ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-rails-rdb-repo:latest

9.ロードバランサー関連

ALBおよびターゲットグループを設定し、トラフィックのルーティング設定を行います。

ターゲットグループの作成

aws elbv2 create-target-group --name hello-world-rails-rdb-tg --protocol HTTP --port 3000 \
  --vpc-id $VPC_ID --target-type ip
export TG_ARN=$(aws elbv2 describe-target-groups --names hello-world-rails-rdb-tg --query "TargetGroups[0].TargetGroupArn" --output text)

ALBの作成と設定

aws elbv2 create-load-balancer --name hello-world-rails-rdb-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-rdb-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

10.ECSクラスターとタスク定義

クラスターを作成し、タスク定義を登録します。

ECSクラスターの作成

aws ecs create-cluster --cluster-name hello-world-rails-rdb-cluster

ECSタスク定義の作成

aws ecs register-task-definition --family hello-world-rails-rdb-task \
  --network-mode awsvpc --requires-compatibilities FARGATE \
  --execution-role-arn arn:aws:iam::$ACCOUNT_ID:role/hello-world-rails-rdb-task-execution-role \
  --cpu "256" --memory "512" \
  --container-definitions '[{"name":"hello-world-rails-rdb-container","image":"'$ACCOUNT_ID'.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-rails-rdb-repo:latest","portMappings":[{"containerPort":3000,"protocol":"tcp"}]}]'

11.ECSサービスの作成

ECSサービスを作成し、ALBと連携してトラフィックの処理を管理します。

aws ecs create-service --cluster hello-world-rails-rdb-cluster --service-name hello-world-rails-rdb-service \
  --task-definition hello-world-rails-rdb-task --desired-count 1 --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=['$SUBNET_ID_1','$SUBNET_ID_2'],securityGroups=['$ECS_RDS_SG_ID'],assignPublicIp='ENABLED'}" \
  --load-balancers "targetGroupArn=$TG_ARN,containerName=hello-world-rails-rdb-container,containerPort=3000"

12.CloudWatchロググループの作成

ECSタスクのログを保存するCloudWatchロググループを作成します。

aws logs create-log-group --log-group-name /ecs/hello-world-rails-rdb-task --region ap-northeast-1

13.ログの確認

CloudWatchログを使用して、ECSタスクが出力するログを確認する。

aws logs describe-log-streams --log-group-name /ecs/hello-world-rails-rdb-task
aws logs get-log-events --log-group-name /ecs/hello-world-rails-rdb-task --log-stream-name $LOG_STREAM_NAME --limit 50

14.ECS更新手順

ECSサービスにデプロイしたアプリケーションを更新する

docker buildx build --platform linux/amd64 -t hello-world-rails-rdb:latest .
docker tag hello-world-rails-rdb:latest $ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-rails-rdb-repo:latest
docker push $ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-rails-rdb-repo:latest
aws ecs update-service --cluster hello-world-rails-rdb-cluster --service hello-world-rails-rdb-service --task-definition hello-world-rails-rdb-task

0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?