hayakasa/docker-vagrant-template-rails
以下の要件を満たすRuby/Ruby on Railsの開発・実行環境を環境を作成しました。
- ホストOSの環境を極力汚さないこと
- 必要最低限の手順で環境構築できること
- 実行環境のバージョンを管理する手間を極力省くこと
- ソースコードを共有ディレクトリでマウントし、編集後に即時反映されること
- Dockerコンテナ側からファイル操作が可能なこと(bundle install、tmp内のファイル作成など)
- Mac・Windowsどちらでも可能な限り同じ手順で構築し動作すること
rvm、rbenvなどで実行環境のバージョン管理をすることが手間に感じていたのでDockerを採用することを決めたのですが、公式で配布されているDocker Desktop for Mac/Windowsにはソースコードを即時反映できるようにマウントした場合に実行速度が遅くなるなどの問題があります。
この問題を解決するため、ホストOSとDockerコンテナの間にVagrantで管理するVMを挟み、共有ディレクトリをNFSでマウントすることによって実行速度を犠牲にせずにアプリ開発ができる環境を作りました。
前提アプリケーションのインストールや使い方は下記GitHubリポジトリのREADMEを参照ください。
hayakasa/docker-vagrant-template-rails
こちらでは、少し突っ込んだ解説を行います。
##NFSについて
Vagrantfileの以下の設定で共有ディレクトリをNFSマウントしています。
config.vm.synced_folder ".", "/vagrant-nfs",type:"nfs" #DocRootをvagrant-nfsという名前でNFSマウント
###Macの場合
Macでは標準でNFSサーバーが準備されているので以下のコマンドで有効化します。
YourPC$ sudo touch /etc/exports #nfsd設定を保存するファイルを作成
YourPC$ sudo nfsd enable #nfsdの有効化
###Windowsの場合
WindowsではVagrantのプラグインを使うことによってNFSサーバーを立てずにNFSでマウントができるためそちらを使用します。
YourPC$ vagrant plugin install vagrant-winnfsd
##vagrant-bindfsプラグインについて
NFSでマウントした共有ディレクトリはホストOSのユーザーがownerになっているので、bindfsでvagrantユーザーがownerになるようにマウントし直します。
config.bindfs.bind_folder "/vagrant-nfs", "/vagrant" #vagrant-nfsをvagrantという名前でbindfsマウント
##vagrant-hostsupdaterプラグインについて
vagrant upでVMを起動するときにhostsファイルにホスト名の登録を行います。これによってホスト名でアプリケーションにアクセスすることができるようになります。
(hostsを操作するためWindowsではコマンドプロンプト・PowerShellを管理者権限で実行する必要があります)
config.vm.hostname = "myapp.localhost"
##ポートフォワーディングについて
以下の設定によって一般的に使用されるポートでホストOSからアクセスができるようにしています。
services:
db:
ports:
- "5432:5432" #例:PostgreSQLの場合。Dockerコンテナの5432番をVMの5432番にポートフォワーディング
app:
command: bundle exec rails s -p 3000 -b '0.0.0.0' --no-dev-caching #rails s を3000番ポートで実行
ports:
- "80:3000" #Dockerコンテナの3000番ポートをVMの80番にポートフォワーディング
config.vm.network "forwarded_port", guest: 80, host: 80 #VMの80番をホストOSの80番にポートフォワーディング
config.vm.network "forwarded_port", guest: 5432, host: 5432 #VMの5432番をホストOSの5432番にポートフォワーディング
##Dockerコンテナの実行ユーザーについて
以下の設定によってRubyのDockerコンテナをvagrantユーザーとして実行します。これによってコンテナ内で作成されるファイルのownerがvagrantユーザーになり、アプリ実行時のパーミッションエラーを回避しています。
services:
app:
user: "1000:1000" #vagrantユーザーのUID:GIDを指定してコンテナを実行
##データベースのvolumeについて
以下の設定によってデータベースのvolumeをVMのディスク領域で永続化しています。したがってVMのイメージ自体を削除しない限り、Dockerコンテナを破棄してもデータベースの中身は保持されます。
services:
db:
volumes:
- /data/db:/var/lib/postgresql/data #例:PostgreSQLの場合 Dockerコンテナの/var/lib/postgresql/dataをVMの/data/dbに保存します