こんにちは、Railsエンジニア見習い補佐のナカハシです。
新しくRailsアプリ開発環境を立ち上げるに辺り、Ruby層まで含めたDocker化をしてみたときのあれこれを残しておきます。
今回の構成
新しく作るRailsアプリは、他のUUUMのRailsアプリのよくある構成と同様、Rails + MySQL + Redis(主にセッション用)の構成にしました。
こういった複数のミドルウェアと組み合わせた動作環境を作る場合、それぞれのDockerコンテナをいい感じに動かすためにDocker Composeを使います。公式ページに Quickstart: Compose and Rails というサンプルがあるので、これを元に設定ファイルを書きました。( rails new
までの手順もここの通りに実施していますので、主な手順もこちらを参照して下さい)
MySQLコンテナとの接続
(ほとんどコピペで)書いたdocker-compose.ymlはこのようになりました。(最初にRedisとも書きましたが、記事の趣旨的に省略しておきます...)
version: '3' services: db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: "password" ports: - "19801:3306" volumes: - ./tmp/db:/var/lib/mysql web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - .:/myapp ports: - "19802:3000" depends_on: - db
これで http://localhost:19802/
にブラウザでアクセスすることで動作確認が出来ます。他のRailsアプリの環境とポートが被るとあれなので、 web
用のポート設定を ports: - "19802:3000"
としています。
DBはプロダクションでの動作環境と合わせてイメージを mysql5.7
とし、ポート番号は web
と同様、他の開発環境にかぶらないように 19801
を設定しています。
この場合、Dockerイメージで動作しているMySQLと同じDockerネットワークにいるRailsアプリからの接続は、以下のようになります。
# database.yml default: &default adapter: mysql2 pool: 5 timeout: 5000 development: <<: *default database: myapp_development username: root password: password host: db port: 3306
ホスト側MacのMySQLクライアントから接続したい場合は 127.0.0.1:19801
で接続します。
$ mysql -u root -h 127.0.0.1 -P 19801 -p
Webサーバー起動失敗
そうこうしてうちに、以下の現象でサーバーの起動に失敗するようになりました(>_<
A server is already running. Check /myapp/rails-app/tmp/pids/server.pid.
pidファイルが不要に残ってしまうことで、この現象になってしまいます。pumaの設定などでpidファイルに関するコントロールはできるとは思うのですが、今回は、愚直に起動前に毎回消すようにします。 UUUMではタスクランナーとしてmakeをよく使います ので、今回は Makefile に以下のように書きました。
.PHONY: run run: rm -rf tmp/pids/server.pid docker-compose up
これで、以下のコマンドでサーバー起動できるようになります。
$ make run
vendor/bundle
よくあるRails環境では、依存Gemをホストのシステム領域ではなく、プロジェクト内のパス vendor/bundle
にインストールしますよね。
$ docker-compose run web bundle install --path vendor/bundle
さて、これで試しに現在のルーティングを確認したりテストを実行してみると、だいぶ時間がかかります。これは、特にGem群がDockerイメージのマウント対象になっていることが原因なようです。
試しに雑に time
コマンドで動作時間だけ計測してみると、、、
$ time docker-compose run web rails routes Starting myapp_db_1 ... done ...(略) You don't have any routes defined! Please add some routes in config/routes.rb. For more information about routes, see the Rails guide: http://guides.rubyonrails.org/routing.html. docker-compose run web rails routes 0.47s user 0.16s system 1% cpu 51.529 total
rails routes
コマンドに1分近くかかっています。。この傾向はrailsコマンド全体で同じですので、単体テストをバリバリ回したいシチュエーションだと相当つらいですね。
docker-compose.yml で以下の設定を追加すると、約20秒まで短縮できました。
version: '3' services: (略) web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - .:/myapp # ★☆ 追加 ★☆ - ./vendor/bundle:/myapp/vendor/bundle:delegated
まとめ
開発環境をDockerに寄せておくと、互換性の問題も発生しにくいしセットアップが簡単になっていいですね。 コーダーやデザイナーとの作業分担時には、特に効果を発揮しそうです。