Ruby2.6.4+Rails6(+Node.js8)+MySQL8+Redis5がすぐにいじれるDockerコンテナを作ってみた


はじめに

WebアプリをRailsで作ろうと思っても、環境を整えるのがめっちゃめんどくさいなぁと感じるときが多々あります。
環境作る前のモチベーションが100だったとしても、前準備にて間取り、ようやくいじれるようになるまでモチベーションが10を切るのはなんともいただけません。

(git,Docker,docker-composeは一通りできることを想定しています)

そこで…

だったら、ちょっとしたコマンド(要Docker,docker-compose)でSandboxを作ってみようと思い、だいたい形になったのでGithubに公開しました。

手に入る環境は以下です

  • Ruby 2.4.6
  • Rails 6.0.0
  • rbenv 最新版
  • MySQL 8.X
  • Node.js 8.X
    • npm
  • Yarn 最新版
  • Redis 5.X

(バージョンの.Xは導入するDockerコンテナの状況に依る)

(補足):結局BundleするときにNode.js(Rails6ではNode.js 8以降)が必要なのでNode.jsの環境も手に入ります

webサービス側のOSとしてcentos7を指定していますが、欲しい環境のパフォーマンスを発揮するためにはいくつかのパッケージが古くなっていたので、以下については外部のパッケージを使用しています。

  • MySQL 8.X
  • Node.js 8.X
  • Yarn

あとは…

リポジトリをcloneして、docker-composeをいくらか実行すればOK!

docker-compose up -d
docker-compose run web bash
cd /work
RAILS_ENV=development rails new hoge --database=mysql webpacker:install

課題(解決済み)

現象

今、railsで素のアプリを作って立ち上げてみたのですが、ホストOSのブラウザから表示できない…。

RAILS_ENV=development rails new startup --database=mysql webpacker:install
cd startup
bundle install
rails s -p 3000 -b '0.0.0.0'
=> Booting Puma
=> Rails 6.0.0 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 3.12.1 (ruby 2.6.4-p104), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop

localhost:3000にリクエストしても…

接続拒否!

IP指定ではどうだろうと、DockerコンテナのIPを調べて、

[root@*** startup]# hostname -i
172.26.0.3

そのIPでリクエストすると…

…タイムアウト…。

何が原因なのだろうか…ここまででなにか原因をご存じの方がいらっしゃいましたらご教授お願いいたします…。

ちなみに、ホストOSはWindows10(64bit)で、Docker for windows desktop 2.1.0.3を使用しています。

経過

docker-compose upしたあとpsすると…

PS L:\DockerContainers\ActionTextSample> docker-compose ps
指定されたパスが見つかりません。
         Name                      Command             State                  Ports
-------------------------------------------------------------------------------------------------
actiontextsample_db_1    docker-entrypoint.sh mysqld   Up       0.0.0.0:3306->3306/tcp, 33060/tcp
actiontextsample_web_1   /bin/bash                     Exit 0

…あ、webのコンテナが落ちてる(涙)

そういえば、docker-compose exec web bash しても コンテナweb_1どこにあるん?とかいうメッセージがあったのですがこれで納得しました。

となると、どうやって立ち上げたままにしようかということで調べると、tty: true を指定するといいよという情報を得ます

docker-compose.yml を編集して再び docker-compose up !

docker-compose.yml
services:
  web:
    build:
      context: ./docker/web/
    :
    tty: true # 追加!
PS L:\DockerContainers\ActionTextSample> docker-compose ps
指定されたパスが見つかりません。
         Name                      Command             State                                 Ports                      
---------------------------------------------------------------------------------------------------------------------------------
actiontextsample_db_1    docker-entrypoint.sh mysqld   Up      0.0.0.0:3306->3306/tcp, 33060/tcp                        
actiontextsample_web_1   /bin/bash                     Up      0.0.0.0:3000->3000/tcp, 0.0.0.0:80->80/tcp, 0.0.0.0:8080->8080/tcp

ちゃんと立ち上がったままになっています!
execを実行してもコンテナに入れます。

PS L:\DockerContainers\ActionTextSample> docker-compose exec web bash
[root@77e31d82d4fb /]#

気を取り直して、rails sしてみてブラウザからアクセスすると…

rails s -b '0.0.0.0'

[root@77e31d82d4fb startup]# rails s -b '0.0.0.0'
=> Booting Puma
=> Rails 6.0.0 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 3.12.1 (ruby 2.6.4-p104), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop

ブラウザから http://localhost:300 で起動すると…あ、アクセスできた!…あら

…やっぱり手抜きはいけませんね。

おとなしく db:migrate とかやるべきですね…database.ymlを開いて修正(passwordとhost)

database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: root # docker-compose.ymlで指定した値
  host: db # mysqlがあるサービスの名前

migrateして

rails db:create
rails db:migrate
rails s -b '0.0.0.0'

ブラウザから http://localhost:3000 でアクセス…例の画像が現れて無事チェク完了!

ちゃんと ruby2.6.4+rails6.0.0で動いてることを確認できます。

ログも特に問題ないようです。

Started GET "/" for 172.28.0.1 at 2019-09-18 04:51:00 +0000
Cannot render console from 172.28.0.1! Allowed networks: 127.0.0.0/127.255.255.255, ::1
   (0.5ms)  SET NAMES utf8mb4,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
Processing by Rails::WelcomeController#index as HTML
  Rendering /usr/local/rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/templates/rails/welcome/index.html.erb
  Rendered /usr/local/rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/railties-6.0.0/lib/rails/templates/rails/welcome/index.html.erb (Duration: 10.5ms | Allocations: 309)
Completed 200 OK in 78ms (Views: 41.0ms | ActiveRecord: 0.0ms | Allocations: 1725)

まとめ

  • 皆さんいい意味でズボラこきましょう!

おまけ

webサービスのDockerfileにはmysql-develだけではなくmysqlも入れています。これは、webコンテナのbashからdbコンテナのDBを確認するために入れています。ホストはコンテナ名で動きました。

mysql -h db -u root -p

補足1(2019.9.25)

なにかの啓示を受けて(笑)、キャッシュ用にRedisコンテナを追加しました。
webサービスで以下のRedisアクセススクリプトを実行してredisサービス側に値が設定されていることを確認しています。

redistest.rb
require 'redis'

redis = Redis.new(host: "redis", port: 6379, db: 2) # host値にはサービス名 "redis" を指定

redis.set("mykey1", "hello")
PS L:\DockerContainers\RailsSandboxByDocker> docker-compose exec redis redis-cli
127.0.0.1:6379> select 2
OK
127.0.0.1:6379[2]> dbsize
(integer) 1
127.0.0.1:6379[2]> keys *
1) "mykey1"
127.0.0.1:6379[2]> get mykey1
"hello"