Vagrantを使ってVM上にJavaのWebアプリ開発環境を作る

# 動作させた環境

* Windows7, 10
* VirtualBox 5.0.8
* Vagrant 1.7.2
* Eclipse 4.5.1(Pleiades)  
  FileSync plugin for Eclipseインストール済み

# ゲスト(VM)側の準備

## vagrantにVMを追加する(**ホスト側の操作**)

```bat
>cd %USERPROFILE%
>mkdir vagrant
>mkdir vagrant\tomcat_dev
>cd vagrant\tomcat_dev
>vagrant box add tomcat_dev https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box
>vagrant init tomcat_dev
```
## Vagrantfileを編集(**ホスト側の操作**)

```vagrant init tomcat_dev```をたたいた後にできるVagrantfileのIPアドレス(192.168.33.10)の部分のコメントを外す
※内容は割愛します。

## 新規追加したVMを起動(**ホスト側の操作**)

```bat
>vagrant up
```

## TomcatサーバーVMの設定(**ゲスト側の操作**)
* VMにSSHでログインしてjava、Tomcatをインストール

```
$ sudo su - 
# yum install -y java-1.8.0-openjdk
# cd /tmp
# wget http://ftp.kddilabs.jp/infosystems/apache/tomcat/tomcat-7/v7.0.65/bin/apache-tomcat-7.0.65.tar.gz
# tar zxvf apache-tomcat-7.0.65.tar.gz 
# chown -R vagrant:vagrant apache-tomcat-7.0.65
# mv apache-tomcat-7.0.65 /opt/
# cd /opt/
# ln -s apache-tomcat-7.0.65 tomcat
# service iptables stop
```
※開発環境だと割り切ってownerをvagrantにしています。
※**8080ポートを見れるようにするために横着してiptablesを止めてますがプロジェクトとかで使う場合は適切に設定してください。**

/opt/tomcat/conf/Catalina/localhost/web-app-project.xmlを作成して以下のように編集

```
<Context path="/web-app-project" docBase="/vagrant/tomcat-webapps/web-app-project" reloadable="true"/>
```


* Tomcatの自動起動設定

/etc/init.d/tomcatを作成

```bash
#!/bin/bash
#
# Startup script for the Tomcat Servlet Container
#
# chkconfig: 2345 35 65
# description: Tomcat is the servlet container that is used in the official \
#              Reference Implementation for the Java Servlet and JavaServer \
#              Pages technologies

TOMCAT_USER=vagrant
CATALINA_HOME=/opt/tomcat

. /etc/rc.d/init.d/functions
prog=tomcat

start() {
    echo -n $"Starting $prog: "
    daemon --user $TOMCAT_USER $CATALINA_HOME/bin/startup.sh > /dev/null
    RETVAL=$?
    if [ $RETVAL -eq 0 ]; then
        echo_success
    else
        echo_failure
    fi
    echo
    [ $RETVAL = 0 ] && touch /var/lock/subsys/$prog
    return $RETVAL
}
stop() {
    echo -n $"Stopping $prog: "
    daemon --user $TOMCAT_USER $CATALINA_HOME/bin/shutdown.sh > /dev/null
    RETVAL=$?
    if [ $RETVAL -eq 0 ]; then
        echo_success
    else
        echo_failure
    fi
    echo
    [ $RETVAL = 0 ] && rm -f /var/lock/subsys/$prog
    return $RETVAL
}

# See how we were called.
case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  restart)
    stop
    start
    ;;
  status)
    INSTANCES=`ps --columns 512 -aef|grep java|grep tomcat|grep org.apache.catalina.startup.Bootstrap|wc -l`
    if [ $INSTANCES -eq 0 ]; then
        echo $prog is stopped
        RETVAL=3
    else
        if [ $INSTANCES -eq 1 ]; then
            echo $prog is running 1 instance...
        else
            echo $prog is running $INSTANCES instances...
        fi
        RETVAL=0
    fi
    ;;
  *)
    echo $"Usage: $prog {start|stop|restart|status|help}"
    exit 1
esac

exit $RETVAL
```

自動起動の設定

```
# chkconfig --add tomcat
# chkconfig tomcat on
```

Tomcatの起動オプションの設定
リモートデバッグできるよう/opt/tomcat/bin/setenv.shを作成して以下のように記述する

```sh
#!/bin/sh
CATALINA_OPTS="${CATALINA_OPTS} -agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n"
export CATALINA_OPTS
```

と書き込んでおきましょう
うっかり変数をJAVA_OPTSでやってしまうとシャットダウンできなくなるので注意です。

**ここまででVM側の設定作業は終了です。一度この状態のVMを保存するので
Export、Importした後に正しくIPが振られるよう、rootで以下のコマンドを実施します。**

```
# ln -s -f /dev/null /etc/udev/rules.d/70-persistent-net.rules
```


## VMをいったん保存、登録のしなおし(**ホスト側の操作**)

```
vagrant halt
vagrant package
vagrant box remove tomcat_dev
vagrant box add tomcat_dev package.box
vagrant up
```

※ここ以前は一度boxを作ってしまえば省略が可能です。


## VM側の構成

ここまででVM側の構成は以下のようになっているはずです。

```
/opt/tomcat
    └conf
        └Catalina
            └localhost
                └web-app-project.xml
/vagrant
    └Vagrantfile
    └tomcat-webapps/      
        └web-app-project/ 
            └WEB-INF/     
                └classes/

```

# ホスト側の準備

## Eclipseの設定

* プロジェクトをVCSから落としてくる  
**%USERPROFILE%\tomcat_dev**(Vagrantfileが置かれているところ)にチェックアウト or クローンします。
ここではWTPとかで利用する動的Webプロジェクトを使っています。
https://github.com/cyubachi-me/web-app-project.git
![image](https://qiita-image-store.s3.amazonaws.com/0/12695/2eb3a75d-ed4c-a666-0ed7-7dca91a40659.png)  
windows側のディレクトリ構成はこんな感じになります。  
   
    ```
C:/Users/xxxx/vagrant/tomcat_dev/
    └Vagrantfile
    └web-app-project/     ←構成は上記画像を参照
    └tomcat-webapps/
        └web-app-project/
            └WEB-INF/
                └classes/        
```

* ファイル同期の設定

    Eclipse上でプロジェクトのプロパティ→ファイル同期と選択して出てきたダイアログ上で以下の画像のように設定します。
![ファイル同期化.png](https://qiita-image-store.s3.amazonaws.com/0/12695/6e72aa4e-acba-b907-92ac-3f89601c8f12.png)
※%USERPROFILE%(C:\Users\xxxxx)の部分は適宜読み替えてください。
    
    最終的なwindows側の構成はこんな感じになっているはずです。

    ```
C:/Users/xxxx/vagrant/tomcat_dev/
        └Vagrantfile
        └tomcat-webapps/
            └web-app-project/
                └WEB-INF/     ←FileSyncPlugin設定ディレクトリ(2)の同期先
                    └lib/     ←FileSyncPlugin設定ディレクトリ(2)の同期先(サブディレクトリ)
                    └classes/ ←FileSyncPlugin設定ディレクトリ(1)の同期先        
```

    VM側のTomcatの設定はautoReload=true(デフォルト)になっているので、    
    1. Eclipse上でソースを編集する
    1. 自動ビルドでbuild/classesが更新される
    1. VM上のTomcatがweb-app-project.xmlに記載されているdocBase:/vagrant/tomcat-webapps/web-app-project/WEB-INF/classes内のclassファイルの変更を検知してアプリのリロード開始
 
    こんな具合でWTPと似た感じで開発できるといった寸法です。


* デバッグ
リモートデバッグでデバッグします。
デバッグの構成→リモートJavaアプリケーション→新規とたどって出てきた画面のホスト名を
192.168.33.10にすればデバッグ可能です。
![リモートデバッグ.png](https://qiita-image-store.s3.amazonaws.com/0/12695/fac19936-8d7f-5154-baf2-9451378876f9.png)
※プロジェクトが存在しないとか出てますが気にしないでください。  
WTPだとデバッグでローカルのTomcatを起動/再起動しますが、この開発環境はVM上にあるので
接続するだけでデバッグできるようになります。

# 使用感とか
正直JavaプロジェクトだけならWTPで素直にやってたほうがいいです。
ゲストのTomcatが結構重いのと、デメリットがそれなりにあるので。。。
Javaのプロジェクト+αみたいな構築がとても面倒なプロジェクトなどに使うと良いかと思います。  


## メリット
まぁ何年も前から言われてるようなことばっかなので今更なのですが

* **開発できるようになるまでがとても速い＆簡単**
これが一番のメリットです。ほかの人の環境で動かないとかそういったことがなくなる上、
プロジェクトに新しい人がジョインしたときなんかにすぐ開発できる状態になります。

* **配布できる**
基底になるようなVMを作れば、「別の案件のデモとかで使いたいから環境1個つくってー」
とかいわれたときにサッと環境が作れたりします。

* **いらなくなったら捨てられる**
Vagrantfileやprovision用のスクリプト、VagrantのboxなんかをSVNやファイルサーバーに登録しておけば
すぐ復帰できるので遠慮なくVMごと削除できるのでディスク容量も抑えられます。

こんなところかと

## デメリット
* **リソースを食う割に遅い。**
  VMのメモリに2GB、TomcatのHeapに1GBだと起動がかなり遅いです。
  2～3万行程度のプロジェクトを起動する際に100秒近くかかりました。
  JSPのコンパイル等にも結構なCPUリソースを持っていかれたりします。


* **Tomcatの再起動がボタン一つでできない、ログがEclipseで見れない**
  開発中にWebアプリをリロードをたくさん実行するとよくOutOfMemoryが出たりしますが 
  そういったアプリ側の異常をキャッチアップすることがEclipseの画面1つでできなかったり、
  Tomcatの再起動がワンタッチでできなかったりします。
  ※終了させることはできるので、再起動自体は工夫次第でどうにかなるような気もしますが・・・。


# 変更履歴
* wgetでtomcatのtar.gzをとってくるコマンドが2個あったので片方削除(11/9)
* /opt/tomcatへのシンボリックリンクの張り忘れがあったのでコマンドを追加(11/9)
* 使用感の見出しのレベルを調整(11/11)