Dockerを使ってGrails開発
Grails開発でdockerを使用するためのDockerfileを、備忘録兼ねて晒します。開発中に使うものです。運用用は、別のものになるでしょうかね。
onesysadmin/docker-grailsを元にして、Proxy設定を行い、いくつかの工夫をしております(プロキシ設定については、Dockerコンテナに透過的プロキシ設定とかをすれば不要なのかも)。
利点
Grails開発でDockerを使う利点は以下の通り。
- 準備が簡単。Grailsのインストールはもとより、gvmやJDKのインストールすらいらない。grails wrapperなどもいらないわけだ。
- 環境を汚さない。JDKのインストールをしなくてすむ、Postgresなどをコンテナに封入して連携する、などによる。
- 設定含めた開発時実行環境を開発メンバー間でシェアできる
- Dockerはlinuxなので、開発環境windows、実行環境linuxによる差異をなくせる。windowsの場合、boot2dockerなどを使って仮想マシン上でlinuxを動かすことになる(MacOSXではDocker 1.3のboot2dockerでホストのフォルダの共有とVOLUME対応(-v指定による共有)がされているそう]だが、まだ試していない。)。
Dockerfileの準備
まず、onesysadmin/docker-grailsをcloneするなりダウンロードするなりして、使用したいGrailsのバージョンのDockerfileを、Grailsプロジェクトのトップディレクトリにコピーします。
Dockerfileの修正
以下に修正点を示します。修正したDockerfile全体はこちらのgistに。
Proxyの設定
開発環境がファイアウォール背後でproxyの設定が必要になる場合は以下のように設定します。今回の場合、プロキシは以下において必要になります。
ENV PROXY_HOST 10.2.3.4 ENV PROXY_PORT 18080 ENV http_proxy http://${PROXY_HOST}:${PROXY_PORT}/ ENV https_proxy http://${PROXY_HOST}:${PROXY_PORT}/
ENTRYPOINT, EXPOSEの設定
ENTRYPOINT [ "/usr/local/bin/gvm-exec.sh", "grails", "-Dgrails.work.dir=/app/.grails" ] EXPOSE 8080
gvm-exec.shや後で出てくるgvm-wrapper.shは「onesysadmin/docker-grails」の親であるイメージ「onesysadmin/gvm」が入れてくれているスクリプトです。
RUN関係
RUN gvm-wrapper.sh install grails 2.4.4 && \ gvm-wrapper.sh flush archives && \ cd /app && \ gvm-exec.sh grails -Dgrails.work.dir=/app/.grails add-proxy client --host="${PROXY_HOST}" --port="${PROXY_PORT}" && \ gvm-exec.sh grails -Dgrails.work.dir=/app/.grails set-proxy client RUN mv /root/.grails/ProxySettings.groovy /root/.grails/ProxySettings.groovy.bak && \ sed -e "s/'http.nonProxyHosts':''/'http.nonProxyHosts':'localhost'/" /root/.grails/ProxySettings.groovy.bak > /root/.grails/ProxySettings.groovy
proxyの設定がポイント。interactiveにしたときでrun-appしてstop-appして再起動したときにportが所有されつづけてしまう問題(address already in useとなる)の回避のため、nonProxyにlocalhostを設定します。
GRAILS_PROJECT/grails-app/conf/BuildConfigの修正
grails.project.dependency.resolutionの「mavenLocal()」を以下のように修正します。
mavenLocal("/app/.m2")
コンテナのビルド
$ cd /path/to/grails/project $ docker build -t you/project .
DBコンテナとの連携
必要に応じて。以下はPostgresを前提とします。
Postgresのコンテナは、以下を参考に「orchardup/postgresql/」を使用します。
- https://registry.hub.docker.com/u/orchardup/postgresql/
- http://deeeet.com/writing/2014/03/20/docker-link-container/
以降、通常のDB接続の設定(ドライバ追加のためにBuildConfig.groovyのdependenciesに「 runtime 'postgresql:postgresql:9.1-901.jdbc4'」を追加するなど)を行なった上での設定です。
DataSource.groovyの修正
driverClassNameやDB認証などの修正
dataSource { pooled = true // jmxExport = true driverClassName = "org.postgresql.Driver" username = System.getenv("DB_ENV_POSTGRESQL_USER") password = System.getenv("DB_ENV_POSTGRESQL_PASS") }
JDBC URLの設定
必要な環境について、URLを設定します。
url = "jdbc:postgresql://${System.getenv('DB_PORT_5432_TCP_ADDR')}:${System.getenv('DB_PORT_5432_TCP_PORT')}/docker"
「docker」はorchardup/postgresqlが初期的にCREATEしてくれるデータベース名です。別の名前にしたいときは、orchardup/postgresqlの起動時にDB名を指定できるので、それにあわせたものを使えば良いでしょう。
DB連携したGarilsコンテナ実行(例)
$ docker run -d -p 5432:5432 -e POSTGRESQL_USER=docker -e POSTGRESQL_PASS=docker --name pg orchardup/postgresql:latest $ docker run -d -p 8080:8080 -v /path/to/grails/project:/app --link pg:db you/project:latest run-app
おまけ
ENTRYPOINTを指定しているので、bashなどを起動したい場合は、
$ docker run -it -v /path/to/grails/project:/app --link pg:db --entrypoint "bash" you/project:latest
こうかな。
まとめ
上記は、Grailsに限らず、開発時にdockerを使用する場合のパターンの一つになると思うが、ホストのディレクトリのマッピング(-v)を駆使してソース含めほとんどのファイルを外に置くコンセプトなので、単独実行するのと使用感も制約もあまりかわらない。しかし、このパターンだと、リモート利用、つまりdockerクライアントを実行するマシンとdockerデーモンが動作するマシンが別の場合には利用できない。つまりdockerデーモンを動かしているホストのlinuxマシンにログインできるアカウントがないと利用できない。dockerは単体でNFSや高速rsyncみたいなものを提供しないのが残念である。できればもっと開発用PaaSっぽく使えるのに!(ADDじゃ遅そうだし動的更新ができない)*2。
このパターンであれば、Eclipse/GGTSなどをdockerで実行するのもそんなに難しくはない。
*1:なお、grails.project.dependency.resolver = "maven"にしているのにもかかわらず、/root/.grails/ivy-cacheが作成され何かが入っている。理由不明
*2:将来的にはFUSEで対応されるかもしれないんだって。やったー。