17
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

(ECS,Rails6)ロードバランサー ALB と データベース RDS とECRを使ってコマンドラインから ECSにRails6のアプリをデプロイ

Posted at

はじめに

ECSの概要とECS CLIを使ってアプリのデプロイの仕方について書いていきます。

ECSやその他のサービスに関して、そこまで理解できてないので間違ってる部分も多いと思います。

とりあえず記事通りに作業したらRails6のアプリケーションをECSにデプロイできる様に記事を書きたいと思います。

もしうまくいかなかったらおそらく権限関係なので権限を見直してみてください。

ECSの概要

ECSはdockerのコンテナをそのままaws上にデプロイできるサービスです。

docker-hubやecrなどのdockerイメージのレジストリからイメージを持ってきてコンテナを作成してデプロイできます。

自分がやった場合、下記の様になりました。

ecs-chart.png

ECSはクラスターと言うEC2のインスタンス群みたいなのをまず作ります。

このクラスター内にEC2があり、その中にECSのタスクと言うのを作ります。

このタスク上でdockerのコンテナが起動される形になります。

dockerコンテナの起動に関してはecsにタスク定義を作成してこのタスク定義を元にdockerコンテナを作成していくことになります。

dockerコンテナの起動に必要なdockerイメージに関してはdockerイメージレジストリから取ってきます。

docker hubの場合は誰でも見れてしまうのでecrを使うのが良いと思います。

作成したコンテナはALBを通して公開されます。

ALBを使うことで負荷がかかった時に新しくタスクの作成し負荷を分散できます。

作成したコンテナに関してはec2インスタンスにkeypairを使ってそこからdockerコンテナにアクセスする形になります。

ちなみにFargateを使う場合は確かコンテナにアクセスできなかった気がします。

デプロイ

前提として

  • PCはMac
  • ローカルPCにdockerとmysqlがインストールされていること

Railsアプリの作成

まずRailsアプリの作成をします。

適当なフォルダを作成してそこに Dockerfile docker-compose.yml Gemfile Gemfile.lock を作成します。

内容は下記の様にします。

Dockerfile

FROM node:13.5-alpine as node

RUN apk add --no-cache bash curl && \
    curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 1.21.1


FROM ruby:2.6.5-alpine

COPY --from=node /usr/local/bin/node /usr/local/bin/node
COPY --from=node /opt/yarn-* /opt/yarn
RUN ln -fs /opt/yarn/bin/yarn /usr/local/bin/yarn
RUN apk add --no-cache git build-base libxml2-dev libxslt-dev postgresql-dev postgresql-client tzdata bash less && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

RUN apk add --no-cache alpine-sdk \
    mysql-client \
    mysql-dev

ENV APP_ROOT /app
RUN mkdir $APP_ROOT
WORKDIR $APP_ROOT

RUN gem update --system && \
    gem install --no-document bundler:2.1.4

ADD ./Gemfile $APP_ROOT/Gemfile
ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock

RUN bundle install

ADD . $APP_ROOT
docker-compose.yml
version: "3"

services:
  db:
    image: mysql:5.7
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_PASSWORD: password
      MYSQL_USER: myuser
      MYSQL_DATABASE: ecs_development
    ports:
      - "3306:3306"
  web:
    build: .
    command: bash -c "yarn install && rails db:migrate && rails s -p 3000 -b '0.0.0.0'"
    ports:
      - "3000:3000"
    volumes:
      - .:/app
    tty: true
    links:
      - db


Gemfile

# frozen_string_literal: true

source "https://rubygems.org" 

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

gem 'rails', '~> 6.0.2', '>= 6.0.2.2'

Gemfile.lockは中身は空でOK

ファイルが作成できたら

docker-compose run --rm web rails new . --database=mysql --skip-bundle --skip-test

このコマンドを実行します。

そうするとrailsのファイルがローカルに作成されていると思います。

config/database.ymlのdevelopmentの部分を下記の様に変更します。

database.yml
development:
  <<: *default
  host: db
  username: myuser
  password: password
  database: ecs_development

そしたら

docker-compose up --build

コマンドを実行します。

コンテナが起動したらrails6はwebpackerを使っているので下記コマンドを実行します。

docker-compose exec web rails webpacker:install

そうするとlocalhost:3000にアクセスすると見慣れた画面が表示されると思います。

スクリーンショット 2020-05-16 22.23.44.png

scaffoldでuserのcrudを作ります。

docker-compose exec web rails generate scaffold user name:string age:integer
docker-compose exec web rails db:migrate

config/routes.rbにroutesを追加します。

routes.rb
root to: "users#index"

これでlocalhost:3000にアクセスすると

スクリーンショット 2020-05-17 10.13.05.png

この画面が表示されると思います。

とりあえずこれでアプリのベースの作成は終わりです。

aws-cli ecs-cliのインストール

デプロイに使うツールをインストールします。

brew install awscli
brew install amazon-ecs-cli

aws configureの設定

aws configureを設定します。

まずIAMユーザーを作る必要があるのでAWSコンソールにアクセスします。

IAMの画面を表示してユーザーの追加ボタンをクリックします。

スクリーンショット 2020-05-17 10.17.13.png

プログラムによるアクセスにチェックをつけ次へボタンを押します。

スクリーンショット 2020-05-17 10.18.18.png

ポリシーのアタッチ画面にて

  • AmazonECS_FullAccess
  • AmazonEC2ContainerRegistryFullAccess

を追加します。

そのまま次へボタンを押していくと最後にユーザーのアクセスキーとシークレットキーが表示されるので保存しておきます。

そしたらaws configureの設定をします。

コマンドラインで

aws configure

と入力して

access_keyとsecret_keyの入力

regionはap-northeast-1と入力します。

これで aws configureの設定は終わりです。

IAMユーザーの権限は不足しているので後々追加していきます。

クラスターの作成

クラスターの作成時にec2のキーペアを設定するのでまずキーペアの作成を行います。

EC2の画面を表示するとそのサイドメニューにキーペアと言うものがあります。

スクリーンショット 2020-05-17 15.11.35.png

このキーペアをクリックしてキーペアを作成し、pemファイルをローカルpcにおきます。

自分の場合はホーム直下にaws-keypairフォルダを作成してそこに置いています。

ファイルに関しては権限を変更しておく必要があります。

自分の場合は下記の上になります。

chmod 400 aws-keypair/qiita-tutorial.pem

ファイルのパスは自分の環境のものに変更してください。

それではECSのクラスターを作成していきます。

クラスターの作成に関してはECS_FullAccessで付与されないが必要な権限が結構あるので別途追加する必要があります。

IAMのポリシーからポリシー作成をクリックします。

ビジュアルエディタでサービス、アクションを選択していきます。

まずIAMに関しては

  • AddRoleToInstanceProfile
  • CreateInstanceProfile
  • CreateRole
  • DeleteInstanceProfile
  • DeleteRole
  • PassRole
  • RemoveRoleFromInstanceProfile
  • AttachRolePolicy
  • DetachRolePolicy

を追加します。

次にEC2に関して

  • DeleteInternetGateway
  • DeleteRouteTable
  • DeleteSecurityGroup

を追加します。

最終的に下記の画像の様になればOKです。

スクリーンショット 2020-05-17 16.36.43.png

ポリシーの作成をしたら作成したポリシーをユーザーにアタッチします。

IAMのユーザーから作成したユーザーをクリックしてアクセス権限の追加をクリックします。

スクリーンショット 2020-05-17 15.44.40.png

そしたら既存のポリシーを追加をクリックして作成したポリシーを追加します。

ポリシーの追加が終わったら

下記のコマンドを実行します。

アクセスキーとシークレットキーに関してはIAMユーザーを作成したときの物を利用してください。

キーペアの名前も自分が作成したキーペアの名前に変更してください。

ecs-cli configure --cluster qiita-tutorial --default-launch-type EC2 --config-name qiita-tutorial --region ap-northeast-1
ecs-cli configure profile --access-key access_key --secret-key secret_key --profile-name qiita-tutorial-profile
ecs-cli up --keypair qiita-tutorial --capability-iam --size 1 --instance-type t2.micro --cluster-config qiita-tutorial --ecs-profile qiita-tutorial-profile

実行するとクラスターの作成が行われます。

--size 1 と設定しているのでec2インスタンスが一つ立ち上がっているはずです。

スクリーンショット 2020-05-17 16.40.58.png

これでクラスターの作成は終わりです。

RDSの作成

デプロイの準備は整いましたがデータベースにrdsを使うのでrdsの作成を行なっていきます。

rdsの画面を表示してデータベースの作成をクリックします。

スクリーンショット 2020-05-17 16.44.46.png

簡単作成、MySQL,無料利用枠を選択します。

DB インスタンス識別子、マスターユーザー名、パスワードを設定して作成します。

作成できたら作成したrdsをクリックすると接続とセキュリティの部分にエンドポイントが記載されています。

ローカルPCからrdsへアクセスができる様にするためにRDSの変更をクリックして

パブリックアクセシビリティ をありにします。

スクリーンショット 2020-05-17 22.08.15.png

またセキュリティーグループの設定も必要なので行います。

作成したrdsのセキュリティーと接続の部分にVPC セキュリティグループの欄があります。

クリックできる様になっているのでクリックします。

rdsのセキュリティーグループが表示されると思います。

インバウンドルールの部分をクリックします。

タイプはMYSQL/Auroraを選択します。

ソースの設定は下記の画像の様にしましたが細かい設定を行いたい場合は適宜行なってください。

スクリーンショット 2020-05-17 22.13.21.png

そしたらローカルPCから下記コマンドでrdsに接続します。

mysql -h rdsのエンドポイント -u rdsのユーザー名 -p

これでパスワードを入力するとrdsに接続できるはずです。

そしたらデータベースの作成を行います。

CREATE DATABASE ecs_development default character set utf8;;

これでrdsにデータベースの作成ができました。

database.ymlの修正

host,username,passwordを環境変数を見る様に修正します。

config/database.yml
development:
  <<: *default
  host: <%= ENV['MYSQL_HOST'] %>
  username: <%= ENV['MYSQL_USER'] %>
  password: <%= ENV['MYSQL_PASSWORD'] %>
  database: ecs_development

ALBの設定

次にALBの設定を行なっていきます。

EC2の画面の再度メニューからロードバランサーをクリックします。

そしたらロードバランサー作成をクリックします。

そしたらApplication Load Balancerの作成をクリックします。

スクリーンショット 2020-05-17 22.37.01.png

まず名前を入力します。

リスナーはそのままで大丈夫です。

スクリーンショット 2020-05-17 22.39.28.png

vpcの設定ですがecsのec2インスタンスのvpcを選択しなくてはいけません。

確認の仕方はクラスターのタスクのコンテナインスタンスをクリックします。

スクリーンショット 2020-05-17 22.41.20.png

ec2インスタンスがあるのでクリックします。

スクリーンショット 2020-05-17 22.41.46.png

ec2インスタンスが表示されます。

したの説明の部分にvpcのidが記載されています。

確認したらそのvpcをロードバランサーの作成の部分のvpcの選択でそれを選択します。

セキュリティーグループは新しいセキュリティーグループを作成をクリックします。

そして下記の画像の様に設定します。

スクリーンショット 2020-05-17 22.56.28.png

ターゲットグループの設定の部分で新しいターゲットグループを選択して名前を入力します。

ターゲットはインスタンスを選択します。

スクリーンショット 2020-05-17 22.44.54.png

次へいくとec2インスタンスの選択画面が出るのでecsで使うec2インスタンスを選択して登録済みに追加ボタンをクリックします。

あとは次へを押して作成すればOKです。

config/environment/development.rbの修正

rails6ではhost名を明示的に記載しないと起動しません。

なのでconfig/environment/development.rbに下記を追加します。

development.rb
config.hosts << ALBdns名を記載

ecrにイメージの登録

ecsで利用するイメージをecrに登録していきます。

ecrの画面を開きレポジトリの作成をクリックします。

適当に名前を入力して作成します。

レポジトリの作成が終わったらローカル環境でdockerイメージをビルドしてpushします。

まず

docker build . -t ecrのURI

を実行します。

そしたら次に下記コマンドでecrにpushします。

aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ecrのURI
docker push ecrのURI

これでecrへのpushはOKです。

デプロイ

デプロイの準備ができたのでデプロイします。

まずデプロイ用のdocker-compose.ymlを作成します。

名前はdocker-compose-deploy.ymlとします。

docker-compose-deploy.yml
version: '3'

services:

  web:
    image: rdsのURI
    command: bash -c "yarn install && rails db:migrate && rm /app/tmp/pids/server.pid && rails s -p 3000 -b '0.0.0.0'"
    environment:
      MYSQL_USER: rdsのuser名
      MYSQL_PASSWORD: rdsのpassword
      MYSQL_HOST: rdsのエンドポイント
      TZ: "Japan"
    ports:
      - "80:3000"
    logging:
      driver: awslogs
      options:
        awslogs-group: ecs-tutorial
        awslogs-region: ap-northeast-1
        awslogs-stream-prefix: web

そしたら

ecs-cli compose -f docker-compose-deploy.yml up --create-log-groups --cluster-config qiita-tutorial --ecs-profile qiita-tutorial-profile

このコマンドを実行します。

そうするとタスクが起動します。

ecsの画面で実行中のタスクに1と書いてあればOKです。

スクリーンショット 2020-05-17 22.33.52.png

もしうまくいかない場合はcloud watchにログが出されていると思うのでそちらを確認してください。

確認

これでデプロイできているはずなのでALBのdns名をurlに貼り付けます。

そうすると....

スクリーンショット 2020-05-17 22.59.38.png

無事開けました。

もちろんデータの登録もできます。

スクリーンショット 2020-05-17 23.05.18.png

コンテナにアクセス

とりあえずこれでデプロイはOKですがecsコンテナにアクセスもしてみます。

まずecsで使われているec2インスタンスのセキュリティーグループを確認してインバウンドルールに関して全てのマイIPからの全てのトラフィックを許可します。

スクリーンショット 2020-05-17 23.11.35.png

ecsコンテナへのアクセスにはsshを使用します。

まずecsで起動しているec2インスタンスのプライベートipをコピーします。

そして

ssh -i keypairのパス ec2-user@ec2インスタンスのパブリックdns

を実行します。

そうするとec2インスタンスにssh接続できるので

docker ps

を実行します。

そうするとコンテナが起動しているので

docker exec -i -t コンテナID bash

を実行するとbashに入れます。

試しに

rails -v

と実行すると

bash-5.0# rails -v
Rails 6.0.3

こう返ってきました

これでecsで起動したdockerへのアクセスはOKです。

終わり

とりあえずこれで終わりです。

いろいろ問題点あるとは思うのでお気づきの点があれば指摘していただけると助かります。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?