開発環境をDockerで開発していたRails6アプリケーションを**AWS(ECS)**にデプロイしている実装で、AWS上にデータベースが作成できない問題が発生したので解決までの手順を残しておこうと思います。
開発環境
- RubyMine
- Ruby 3.0.1
- Ruby on Rails 6.1.3
- Docker 20.10.7
- AWS (ECS fargate/ECR/VPC/RDS/ACM/ALB/S3/Route53)
発生していた問題
オリジナルアプリをDockerで開発していたので、デプロイ先を**AWS(ECS fargate)**にしたいと思い実装を進めているなかで、本番環境でデータベースが作成されないエラーが起きました。
エラー内容(ECSタスク上のログ)
2021-07-26 19:26:48Tasks: TOP => db:create
2021-07-26 19:26:48(See full trace by running task with --trace)
2021-07-26 19:26:48rails aborted!
2021-07-26 19:26:48ActiveRecord::ConnectionNotEstablished: Unknown MySQL server host 'db' (-2)
2021-07-26 19:26:48Caused by:
2021-07-26 19:26:48Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2)
2021-07-26 19:26:48Unknown MySQL server host 'db' (-2)
2021-07-26 19:26:48Couldn't create 'locat' database. Please check your configuration.
エラー文を調べたところ、サーバーホスト名dbが本番環境で見つからないというエラー内容だとわかりました。
修正前のdatabase.yml
# MySQL. Versions 5.5.8 and up are supported.
#
# Install the MySQL driver
# gem install mysql2
#
# Ensure the MySQL gem is defined in your Gemfile
# gem 'mysql2'
#
# And be sure to use new-style password hashing:
# https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html
#
default: &default
adapter: mysql2
encoding: utf8
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: password
socket: /tmp/mysql.sock
host: db
development:
<<: *default
database: locat_development
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: locat_test
production:
<<: *default
database: <%= Rails.application.credentials.db[:database] %>
username: <%= Rails.application.credentials.db[:username] %>
password: <%= Rails.application.credentials.db[:password] %>
socket: <%= Rails.application.credentials.db[:socket] %>
# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password or a full connection URL as an environment
# variable when you boot the app. For example:
#
# DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase"
#
# If the connection URL is provided in the special DATABASE_URL environment
# variable, Rails will automatically merge its configuration values on top of
# the values provided in this file. Alternatively, you can specify a connection
# URL environment variable explicitly:
#
# production:
# url: <%= ENV['MY_APP_DATABASE_URL'] %>
#
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full overview on how database connection configuration can be specified.
#
エラー原因
エラー原因は、ローカルのmysqlサーバーホスト名
**'db'**でECS上で設定しているRDSとの連携をしようとしていたことが原因でした。
つまり、ローカルの接続先ホストをRDSのエンドポイントにして連携させてあげる必要がある。
ローカルのホスト名と本番環境のRDSを同じにしてあげないと、RDS上にはない**'db'**で接続しようとしてしまいデータベースが作成できないエラーが発生してしまうということでした。
解決方法
ローカルの接続先ホストをRDSのエンドポイントに指定してあげることでデータベースの作成ができました。
修正方法
% EDITOR=vim bin/rails credentials:edit
でhost
を作成してRDSのエンドポイントを指定する
#aws:
# access_key_id: AKIAU2S6QQYAB4JOXSO6
# secret_access_key: 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
# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
db:
database: RDSのデータベース名
username: RDSのユーザー名
password: RDSのパスワード
socket: xxxxxxxxxxxxxxxxxxxxxxxxx
host: ここにRDSのエンドポイントを指定してあげる
-
credential.yml
にエンドポイントを指定すると、ECSで作成するコンテナの環境変数にエンドポイントを設定する必要はなくなる(設定しても可)
credential.yml
に必要なエンドポイントを指定したあとは、database.yml
を下記のように編集する
database.yml
production:
<<: *default
database: <%= Rails.application.credentials.db[:database] %>
username: <%= Rails.application.credentials.db[:username] %>
password: <%= Rails.application.credentials.db[:password] %>
socket: <%= Rails.application.credentials.db[:socket] %>
host: <%= Rails.application.credentials.db[:host] %>
-
host: <%= Rails.application.credentials.db[:host] %>
を設定する
ここまで修正したらECRに設定したリポジトリのlatestを削除後にプッシュを行う。
(Rails側のDockerfileをプッシュ)
-
CircleCI
を導入している方は自動デプロイで可能。
タスク定義のリビジョンで
コンテナの再定義を
行う。再定義後にクラスターのサービス名の設定内のリビジョン
を変更した最新のlatestに変更。
- ここまで修正したらタスクのログでデータベースが作成できているか確認をしてみる。(おそらくデータベースの作成ができているでしょう。)
まとめ
初めてECSに触れたので、デプロイまでの実装でかなりつまずきました。ひとまずデータベースの作成ができたので一安心。
インフラ周りが自分の中で最も難しい分野だと感じているので、知識を増やして正しく構築できるように勉強していこうと思います!