読者です 読者をやめる 読者になる 読者になる

圧倒亭グランパのブログ

圧倒的おじいちゃんを目指して

Vagrantの重要ファイル「Vagrantfile」の読み込みとその周りの挙動をちょっと細かく追ってみた

だんだん秋めいてきて、毎日の服装に迷っている@at_grandpaです。

長袖だと日中暑いですし、半袖だと夕方寒いです。
体調を崩しやすい季節ですので、みなさんお気をつけください。

 

前回までで、Vagrantを用いた仮想環境の立ちあげ〜ログインまでを行いました。

今回は、Vagrantをいじくりまわす上で重要なファイルである Vagrantfile について書こうと思います。

参考にしているサイトは、以下です。

 

Vagrantのコードを全て追ったわけではありません。(検証はしていますが)
※その点に注意して読んでいただければと思います。

 

Vagrantfile

どんな役割のファイルなのか

Vagrantfile は VMを立ち上げる際のconfigやprovision(立ち上げ時自動実行)を記述するファイル です。
前回の操作の際は、vagrant init を行った時点で、カレントディレクトリに作成されていました。

Vagrantfileは、ひとつのプロジェクトに最低ひとつ必要です。
また、gitなどでバージョン管理をすることができるので他の人との開発にも便利です。

Vagrantfileを編集してできることは、以下のようなものがあります。

  • VMを立ち上げる際のboxの指定
  • IP、ポートの設定
  • VM立ち上げ時に、自分で書いたシェルスクリプトを走らせる
  • VM立ち上げ時に、Chef-Soloを実行し開発環境を整える
  • 複数のVMを立ち上げられるようにする
  • etc...

まだまだ機能がありますが、これだけでも相当なことができると思います。

Vagrantfile は Ruby で書かれていますが、簡単な変数代入で書かれているため、
公式にも「Rubyの知識は必要ない」と書いてあります。

この部分も、導入の敷居を下げるのに貢献しているのかもしれませんね。

 

Vagrantfileの読み込み

読み込みの流れ

Vagrantfile は、以下の4ステップで読み込まれます。
あるステップでVagrantfileが存在しなかった場合は、そのステップを飛ばして次のVagrantfileが読み込まれます。

  1. Vagrantによって予め作成されているVagrantfileを読み込む。デフォルト設定が書かれており、編集すべきではない。
  2. 設定したboxに含まれているVagrantfileを読み込む。boxファイルを作成するときに作る?(未調査)
  3. VagrantのホームディレクトリにあるVagrantfileを読み込む。デフォルトでは ~/.vagrant.d
    これにより、システムユーザーにデフォルト設定を指定できる。
  4. プロジェクトディレクトリのVagrantfileを読み込む。vagrant initしたディレクトリに作成される。一番よく編集する。

それぞれのステップにVagrantfileがあった場合、一体どのファイルの内容が実行されるのかが気になるところです。
いろいろ検証してみました。

 

Rubyをちょっと勉強する

Vagrantfileの内容を見てみると、以下のような形式になっています。

Vagrant::Config.run do |config|
...
end

今回のこのブログで初めてRubyを触っているわけですが、いろいろ調べてみました。 するとこの部分は、Vagrantオブジェクト、Configメソッド、runメソッドがあり、
その返り値をforeach風に回しているんだと思います。

このことから、

  ・何らかのメイン処理があり、そこでVagrantオブジェクトが生成される
  ・VagrantfileはVagrant::Config.runメソッドの返り値をループ処理するためにrequireされている

と仮説が立てられます。

Vagrantfileが複数ある場合は、その個数分だけrequireされ、Vagrant::Config.runメソッドが走ります。
インスタンス変数は、Vagrant::Config.runメソッドの返り値がループ処理されるたびに上書きされていきます。
(ex:VM立ち上げ時にはOSを1つだけ指定するので、box-nameは一番最後に読み込まれたVagrantfileのものになる)
また、配列に値がどんどん追加されていく、という形も考えられます。
(ex:provision(自動実行処理)などは、処理内容をどんどん追加して最後に全て実行する形)

だんだんとVagrantfileの読み込み、実行、変数の内容の決定方法がわかってきました。

 

実際の処理はいつ走るのか

ここで疑問になったのが、実際の処理はいつ走るのかです。

まぁ、大体の構成として「オブジェクトの内容を全て決定してから最後に実行」なのだろうと予想がつきます。
でも確かめてみたくなるのが人情。やってみましょう。

簡単です。Vagrantfile内でtextを出力させ、どのような順で出力されるかを検証します。
テスト用のVagrantfileは以下です。それぞれ保存先が違います。

#~/.vagrant.d/Vagrantfile
print "11111111" + "¥n"
Vagrant::Config.run do |config|
    # ここにいろいろな設定
    print "22222222" + "¥n"
end
print "33333333" + "¥n"
#./Vagrantfile
print "hogehoge" + "¥n"
Vagrant::Config.run do |config|
    # ここにいろいろな設定
    print "fugafuga" + "¥n"
end
print "piyopiyo" + "¥n"

vagrant upした際の出力結果はこうなりました。

$ vagrant up
11111111
33333333
hogehoge
piyopiyo
22222222
fugafuga
[default] VM already created. Booting if it's not already running...
[default] Clearing any previously set forwarded ports...
[default] Forwarding ports...
[default] -- 22 => 2222
...

結果を見てみると、

  • 実際の処理の前にprintされていることから、全てのVagrantfileがVM立ち上げ処理の前に読み込まれている
  • 読み込まれる順は、~/.vagrant.d/Vagrantfile./Vagrantfile
  • この順番で、まずは全てのVagrantfileのVagrant::Config.run do |config| 〜 end外側部分が実行される
  • 次に、この順番で、全てのVagrantfileのVagrant::Config.run do |config| 〜 end内側部分が実行される

となっています。

Rubyというものはこういうものなんですかね。その辺、勉強不足です。

このような流れで、インスタンス変数の上書きや、配列への値の追加がなされています。

これで、Vagrantfileの読み込みから実行までを追うことができました。

 

【補足】探索する順序

ステップ4でカレントディレクトリ内のVagrantfileが存在するかを確認していますが、
もし無い場合は、以下のようにディレクトリツリーを上に遡って検索していきます。

/hoge/fuga/piyo/Vagrantfile
/hoge/fuga/Vagrantfile
/hoge/Vagrantfile
/Vagrantfile

これにより、プロジェクトのどこからでもvagrantコマンドを実行できます。

 

まとめ

今回はVagrantの中核をなすファイル、Vagrantfileとその周りの挙動について追ってみました。

  • Vagrantのメイン処理が走ると、Vagrantオブジェクトが生成される
  • そのメイン処理の中で、Vagrantfileがrequireされる
  • Vagrantfileは複数存在することもあり、読み込まれる順番が決っている
  • Vagrantfileには、「Vagrant::Config.runメソッドの返り値をループ処理する」際の挙動が書かれている
  • 複数のループ処理が走る(Vagrantfileが読み込まれる)と、それに応じて変数が上書きされたり、配列に値が追加されたりする
  • こうして、様々な設定がなされたVagrantオブジェクトが作り上げられていく
  • 全てのVagrantfileを読み込み、Vagrantオブジェクトが完成した時点で、VM立ち上げ処理を実行する

Rubyistの方は「そんなの当たり前の処理じゃん」と思われるかもしれませんが、
Ruby初心者の自分にとっては、処理が追えたのはテンション上がりました。

細かく処理が追えたことで、今後のVagrantfileの編集の手助けになりそうです。

 

次回は、Vagrantfileを編集し、複数VMの立ち上げ を行いたいと思います。

お茶でも飲みながら読んでくださればと思います。

温かいお茶が美味しくなってくる季節ですしねぇ〜。