こんにちは、サービス開発の千葉(@kachina_t)です。 暖かかったり寒かったり、花粉だったり、空が黄色かったりと大変ですが、みなさま無事ですか?
わたしはと言うと、すこしの花粉症と一緒に Herokuで公開しているRailsアプリを、Beanstalk環境へ移行すべく悪戦苦闘しています。
花粉症の対策ついては他所へ譲るとして、ここではHerokuで公開しているRailsアプリを Beanstalkへ移行する手順について書きたいと思います。
などと考えていたのですが、なんとも超大作になりそうなので、コレもまた別の機会へ譲り 本稿では、地味にツマヅイた文字コードまわり database.ymlに『encoding:utf8』を設定したダケではウマいことやってくれない。 について書きたいと思います。 (※:Beanstalkについては 『AWS Elastic Beanstalkを使ってみた』 をご覧ください)
それでは、さっそく初めていきたいと思います。
事前情報
ebコマンドにてアプリケーションの構築をする際に、RDSを作成を指示することが可能です。 これによりRDS(MySQL5.5)付きのBeanstalk環境が構築されます。
【コマンド】
$ eb init 〜〜 中略 〜〜 Create an RDS DB Instance? [y/n] (current value is "Yes"): Yes 〜〜 中略 〜〜
アプリ側の設定
RailsアプリのDB設定は、以下の様に定義することで動的にRDSの情報を取得することが可能です。 (※:弊社の開発環境では『database.yml』はコミットしないルールなのでexampleファイルとします) 以降の例では、production環境に対してreleaseブランチをデプロイします。
【~/config/database.yml.example】
production: adapter: mysql2 encoding: utf8 database: <%= ENV['RDS_DB_NAME'] %> pool: 5 username: <%= ENV['RDS_USERNAME'] %> password: <%= ENV['RDS_PASSWORD'] %> host: <%= ENV['RDS_HOSTNAME'] %> port: <%= ENV['RDS_PORT'] %>
これは実行環境の環境変数を取得するように記載しているのですが RDSの情報以外にも、様々な動的な値が取得可能ですので 一度、実行環境にて以下のファイルをご確認することをオススメします。 『/opt/elasticbeanstalk/support/envvars.d/sysenv』
また、ローカル側の『~/.elasticbeanstalk/optionsettings.production』ファイルの 『[aws:elasticbeanstalk:application:environment]』に 追記することで独自の環境変数をセットすることも可能です。
【~/.elasticbeanstalk/optionsettings.production】
[aws:elasticbeanstalk:application:environment] FOO=BAR
デプロイコマンドの定義
ローカル側に『.ebextensions/container_commands.config』を作成し デプロイに必要なコマンドを定義します。 (※:ファイル名は任意ですが、拡張子は『.config』としてください)
【.ebextensions/container_commands.config】
container_commands: 01-database_config: command: cp config/database.yml.example config/database.yml 02-bundle_install: command: bundle install --path vendor/bundle 03-db_migrate: command: bundle exec rake db:migrate 04-db_seed: command: bundle exec rake db:seed 05-assets_precompile: command: bundle exec rake assets:precompile 06-chown: command: chown -R webapp:webapp ./
デプロイ時に『container_commands』の内容をroot権限で実行されます。 注意して頂きたい点としては、コマンドはrootユーザ権限で実行しますが、アプリケーションはwebappユーザ権限で実行されます。 この為、例では『06』でリソースのオーナーを変更しています。
環境の構築
これでやっと環境を構築する為の準備が整いました。
コマンド
$ eb start
ELB、EC2、RDS等が起動するまで10分程お待ちください。
RDS:パラメータグループの設定
『eb start』コマンドで起動したRDSには、デフォルトのパラメータグループが適用されているので 文字コードが『utf8』のパラメータグループを作成し設定します。 【パラメータグループを作成】 → 【『Viewing』を『character_set_』で検索した結果の全ての値を『utf8』に変更】 → 【対象RDSへ設定】 → 【再起動】します。
RDS:DBの文字コードを変更
『eb start』コマンドで起動したRDSには『ebdb』という名前のDBが作成されます。 これは『<%= ENV['RDS_DB_NAME'] %>』で取得するDB名と同じ物なのですが 将来的にBeanstalkの仕様が変わる可能性もあるので、設定ファイルでは環境変数を参照するようにしておきます。
先程、character_set辺りの設定を全て『utf8』にしたパラメータグループを設定したので 今後作成するDB、テーブル、カラムは『utf8』となりますが 既に作成されてしまっている『ebdb』DBは文字コードが『latin』のままとなります。 なので、実行環境から以下のコマンドを実行しDBの文字コードを変更します。
【コマンド】
mysql -h $RDS_HOSTNAME -u $RDS_USERNAME -p $RDS_DB_NAME alter database ebdb character set utf8;
アプリケーションのデプロイ
これでやっとアプリケーションのデプロイが可能です。
【コマンド】
git aws.push release
以上で、マルチバイトが利用可能なRails+Beanstalkの環境が構築できました。
その他の方法
上記以外にも、様々な方法があると思います。 参考までに、検討した内容と、良策ではないと判断した理由を記載します。
【BeanstalkにRDSを含めない】
複数環境を構築した際に、アプリ対DBの関係情報を別に管理する必要となります。 また、環境を削除する際にRDSを消し忘れる恐れアリ。 → メンドウ、自分自身が忘れる自信があるのでNG
【migrateファイルのcreate_tableオプションで文字コードを指定する】
テーブルを追加する際に、忘れずにオプション値を追記する必要があります。 → メンドウ、自分自身が忘れる自信があるのでNG
【ebdbとは別のDBを作る】
『container_commands』あたりを上手につかえば、実現可能なのですが Beanstalkが用意したDBを使えていない感じがダサいのと 後から入ったメンバーがBeanstalkが作成する『ebdb』の中身が空っぽだと、その理由を調べる手間が増える。 → 上記の理由でNG
まとめ
『実行環境』へsshや、『mysql』コマンドを使うことなく実現できればカッコイイのですが 初回に1回だけってトコロで妥協し、この方法で着地しました。
他に良案があれば、@kachina_tマデご連絡頂けるとウレシイです。