動機
昨今の開発において、常識になっているDocker。
私もそろそろ学ばねばということで、書籍を使って概要を掴みました。
仕組みと使い方がわかる Docker&Kubernetesのきほんのきほん (Compass Booksシリーズ)
- 作者:小笠原 種高
- $1
Dockerの仕組み、Dockerfile、Docker Composeの基本はわかったけれど、実際にRailsアプリを動かしてみたらどうなるんだろう?と気になっていたところ、RubyMineの公式がDocker Compose環境でRailsを動かすサンプルRailsを公開していたので、Railsアプリの起動までやってみました。
やること
チュートリアル: リモートインタープリターとしての Docker Compose | RubyMineをやる
サンプル$1:
やってみる
まずはgit clone
コマンドでも構いませんが、RubyMineを使用しているので、「Get from VCS」からサンプルVCSのURLを設定して、cloneを実施します。
DB設定をPostgresqlに変更する
cloneした時点ではDB設定がsqlite3になっているようなので、config/database.yml
を開き、使用するDBを変更します。
コンテナを起動する
次にdocker-compose.yml
を開いて、ガターにある矢印アイコンを押します。
これで/usr/local/bin/docker-compose -f /Users/tadokoroikuma/RubymineProjects/sandbox/sample_rails_app/docker-compose.yml up -d
というコマンドが実行されます。
つまりは、このdocker-compose.yml
をベースとして、バックグラウンドでサービス(コンテナ)を起動するわけです。
これでPostgresqlとRubyのコンテナがそれぞれ作成&起動されます。
Rubyーとして、コンテナ上のRubyを指定する
次にRubyMineに対して、コンテナ上のRubyを参照するように設定します。
Preferences > Ruby SDK and Gemsを開き、「+」から「New Remote」を選択します。
続いて、Docker ComposeのwebコンテナのRubyを参照するように設定し、「OK」を押します。
DB作成と$1を行う
次にrails db:create
とrails db:migrate
を実施します。
これに限らずですが、ターミナルからコンテナに入ってコマンドを直接実行する方法と、RubyMineの機能を使って実行する方法の2種類があるので、それぞれ解説します。
ターミナルからコンテナに入ってコマンドを直接実行する方法
RubyMineの機能を使って実行する方法
RubyMineのRunAnythingに包含されている、Rake Taskの実行を用いて起動します。
(rakeタスクのコマンドはrailsコマンドに移管されたのですが、RubyMineの機能を使う場合は、Rakeタスクとして扱う必要があります。というかRailsコマンドで実行しても結局はRakeタスクを叩いているだけなので…)
^
を2回押して、RunAnythingを呼び出し、rake --tasks
と入力してEnterで実行します。
これをしないとどうもDocker環境でRakeタスクが認識できないようで…(これは不便)。
これでRakeタスクが使えるようになったので、RunAnythingからrake db:create
を実行します(rake db:migrate
も同様)
DBが作成されたか確認する
$1にはありませんが、RubyMineのDBクライアント機能を使って作成されたDBを確認してみましょう。
まずはDatabaseツールウィンドウを開いて、「+」ボタンからDataSourceとしてPostgreSQLを選択します。
次に接続に必要な情報を以下の通り設定していきます。
項目 | 設定 | 説明 |
---|---|---|
Port | 54333 | docker-compose.ymlで設定したポート$1ードにもとづき、54333を指定します。 |
Authentication | User & Password | postgresのコンテナの設定にしたがい、この認証方法を指定します。 |
User | postgres | database.ymlで定義した内容に従って、postgresを指定します |
Password | <空欄> | docker-compose.ymlで指定した内容にて、パスワード不要のオプションを設定しているため、空欄にします |
Database | sample_rails_app_db | database.ymlで指定した内容に基づき、この名前のDBへの接続を指定します |
入力が完了したら、TestConnectionを行い、問題なければOKを押してください。
うまくいけばこのようにDatabaseの中身を確認することができます。
Railsアプリケーションの実行
RAILSの実行対象に「DEVELOPMENT:SAMPLE_RAILS_APP」を指定し、再生ボタンを押します。
ブラウザを開き、http://0.0.0.0:3000/
にアクセスするとサンプルアプリが起動します。
なおターミナルから実行する場合は以下のようにします。
バインドマウントがされているか確認してみる
後述のdocker-composeの設定で、node_modulesを除くすべてのファイルの変更がコンテナ上に反映されます。
実際にソースを少し改変して、反映されることを確認してみましょう。
app/views/static_pages/home.html.erb
を開き、23行目にある内容を書き換えてみましょう。
この状態でアプリをリロードします。
たしかに内容が変更されていることが確認できました。
定義ファイルを確認する
ここまでで実際にRailsアプリを立ち上げることができました。ここからはこの環境を作成した定義ファイルを確認していきたいと思います。
docker-compose.yml
まずはdocker-compose.yml
からです。
順番に見ていきます。
これは使用するDocker Composeのバージョンを指定しているだけです。
今回はバージョン3を指定しています。
次にservices、つまり使用するコンテナの設定です。今回はdbというコンテナとwebというコンテナの2種類を立てます。
順を追ってみてみましょう。まずはdbコンテナです。
以下各定義内容の説明です。
定義 | 意味 |
---|---|
image:postgres | dbコンテナではpostgresqlをイメージとします |
volumes | docker-compose.yml からみた$1でvar/lib/postgresql/data が呼び出されたら、ホストの./tmp/db に読み取り、書き込みを行います。これによりデータが永続化できます |
environment | Postgresqlとして、POSTGRES_HOST_AUTH_METHOD を定義し、その値にtrust を指定します。このオプションはPostgresqlのパスワードが不要になるもので、推奨はされていません(今回は検証用のPostgresqlなので…) |
ports | ホストのポート54333を5432にポート$1ードします。 |
volumes
の指定は、Dockerの2つある方法のうちの「バインドマウント(Dockerエンジン上ではなく、ホストの指定した箇所に保存する)」の指定で、:
を境にホスト:コンテナのように指定されています。
参考:Postgres - Official Image | Docker Hub
続いてwebコンテナを確認します。
こちらも同様に各定義内容の説明です。
定義 | 意味 |
---|---|
build | docker-compose から見た$1で. つまり、カレント$1リにあるDockerfileをベースにしてコンテナを作成します。 |
command | コンテナ起動時のコマンドを指定する。tail -f /dev/null は何もしないで起動を続けるためのコマンドで、RubyMine側でRailsを起動する際に、コンテナ内でRailsが立ち上がっているとプロセスが重複して起動できなくなることを回避するために、このようにしています。 |
volumes | 一行目は、コンテナの./sample_rails_application に対して、ホストの. (カレント$1リ)をバインドマウントしています。2行目はコンテナ上のnode_modules $1リを名前なしボリュームとしてマウントしています |
ports | ポート$1ードを定義しています |
depends_on | dbコンテナに依存することを定義しています |
結構ややこしいのが、node_modules
の名前なしボリュームでのマウントです。
まず先の通り、手元のソースの反映はバインドマウントによって、すべてコンテナ上と同期されます。
こうすると、ホスト上とコンテナ上のnode_modules
がそれぞれ同期されてしまうのですが、せっかくコンテナ上で固定したnodeが、ホストによって破壊されることになってしまいます。
そのため、node_modules
のみはバインドの対象外とするのですが、コンテナが破棄されたのちもデータを永続化するため、DockerEngine上に名前なしボリュームとしてマウントする手段をとっています。
参考:VSCode&Docker Volumeにおけるnode_modules問題を解決する
ここまでに記述した内容でたしかにコンテナが起動しているかは、コマンドでも確認することができますが、RubyMineのServicesタブを使って確認することができます。
webコンテナのポート$1ード設定を確認
Dockerfile
つづいて、Dockerfileです。
このimageを元に、docker-composeのwebコンテナは作成されるようです。
感想
素晴らしい書籍のおかげでDockerの基礎を理解できたのはよいものの、実際にRailsアプリを一から起動するとなると、ややハードルが高かったです。
しかしながら、この$1はすでに出来上がっている$1を使ってアプリを動かすので、その中継点として非常にちょうどいい題材だと思いました。
一点気になったのが、node_modulesはVolumeTrickを使って名前なしボリュームにマウントしているのに、Gemfileはいいのか?というところです。
なんか同じような類なので、Gemfileもボリュームマウントした方がいい気がするんですが、その話はまた別の機会に調べようと思います。