前回Docker ComposeでSailsの開発環境を用意しました。Clojureの勉強用環境もDocker Composeで作ってみます。開発用のJavaはDockerコンテナを使いながら、ホストマシンのEmacsを使ってコードを編集できるようにします。
プロジェクト
プロジェクトのディレクトリを作成します。Dockerfile、docker-compose.yml、m2ディレクトリを作成します。
$ cd ~/clojure_apps
$ tree .
.
├── Dockerfile
├── docker-compose.yml
└── m2
DockerとDocker Composeのバージョンを確認しておきます。
$ docker version
...
Server version: 1.6.0
$ docker-compose --version
docker-compose 1.2.0
Dockerfile
ベースイメージはオフィシャルのclojureを使います。Dockerホストの作業ユーザーと同じuidでユーザーを作成して、ボリューム内に作成されたファイルを編集できるようにします。
FROM clojure
MAINTAINER Masato Shimizu <ma6ato@gmail.com>
WORKDIR /usr/src/app
RUN apt-get update && apt-get install sudo net-tools && \
rm -rf /var/lib/apt/lists/*
RUN adduser --disabled-password --gecos '' --uid 1000 docker && \
adduser docker sudo && \
echo 'docker ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers && \
mkdir /home/docker/.m2 && \
chown -R docker:docker /usr/src/app /home/docker/.m2
VOLUME /home/docker/.m2
USER docker
RUN lein
ENTRYPOINT ["lein"]
Dockerイメージは開発中も変更がないのでローカルにビルドしておきます。
$ cd ~/clojure_apps
$ docker build -t clojure .
REPL
Clojure REPLを実行するための基本的なdocker-compose.ymlを用意します。WORKDIR
の/usr/src/app
をカレントディレクトリにマップします。
lein: &defaults
image: clojure
volumes:
- .:/usr/src/app
- ./m2:/home/docker/.m2
Docker Composeのleinサービスをワンショットで実行します。初回実行時に/home/docker/.m2
にMavenよりjarファイルがダウンロードされます。.m2
ディレクトリはDockerホストにマップしているので2回目以降からはダウンロード済みのjarファイルを使います。
$ cd ~/clojure_apps
$ docker-compose run --rm lein repl
...
nREPL server started on port 54118 on host 127.0.0.1 - nrepl://127.0.0.1:54118
REPL-y 0.3.5, nREPL 0.2.6
Clojure 1.6.0
OpenJDK 64-Bit Server VM 1.7.0_79-b14
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
user=>
Compojure
WebフレームワークのCompojureを使ったプロジェクトを作成してみます。
$ cd ~/clojure_apps
$ docker-compose run --rm lein new compojure hello-world
Retrieving compojure/lein-template/0.4.2/lein-template-0.4.2.pom from clojars
Retrieving compojure/lein-template/0.4.2/lein-template-0.4.2.jar from clojars
Removing clojureapps_lein_run_1...
カレントディレクトリにCompojureのプロジェクトが作成されました。
$ tree hello-world/
hello-world/
├── README.md
├── project.clj
├── resources
│ └── public
├── src
│ └── hello_world
│ └── handler.clj
└── test
└── hello_world
└── handler_test.clj
Docker ComposeからCompojureを起動するためにdocker-compose.ymlを編集します。working_dir
にComposeプロジェクトのディレクトリを指定します。
lein: &defaults
image: clojure
volumes:
- .:/usr/src/app
- ./m2:/home/docker/.m2
working_dir: /usr/src/app/hello-world
ports:
- "3000:3000"
Ringサーバーを起動します。lein ring server
で起動するとNo X11 DISPLAY variable was set
とエラーがでてしまいます。ヘッドレスなDockerなのでlein ring server-headless
で起動します。また--service-ports
フラグを指定してDockerホストにポートをマップします。
$ docker-compose run --rm --service-ports lein ring server-headless
...
2015-05-16 09:42:00.573:INFO:oejs.Server:jetty-7.6.8.v20121106
2015-05-16 09:42:00.608:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:3000
Started server on port 3000
初回起動時にはjarファイルをダウンロードするためすこし時間がかかります。Dockerホストで別のシェルを起動してサーバーの起動を確認します。
$ curl -s localhost:3000
Hello World
Clojure Script REPL
CompojureプロジェクトでClojure Script REPLを使ってみます。project.clj
に:plugin
と:cljsbuild
ディレクティブを追加します。Clojureは1.6を使っているのでClojure Scriptは1.6系の0.0-3126
を指定します。
(defproject hello-world "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:min-lein-version "2.0.0"
:dependencies [[org.clojure/clojure "1.6.0"]
[compojure "1.3.1"]
[ring/ring-defaults "0.1.2"]
[org.clojure/clojurescript "0.0-3126"]]
:plugins [[lein-ring "0.8.13"]
[lein-cljsbuild "1.0.6"]]
:ring {:handler hello-world.handler/app}
:profiles
{:dev {:dependencies [[javax.servlet/servlet-api "2.5"]
[ring-mock "0.1.5"]]}}
:cljsbuild {
:builds [{
:source-paths ["src-cljs"]
:compiler {
:output-to "resources/public/main.js"
:optimizations :whitespace
:pretty-print true}}]}))
docker-compose.ymlはClojure Script用のサービスをcljslein
としてlein
サービスをマージして用意します。
lein: &defaults
image: clojure
volumes:
- .:/usr/src/app
- ./m2:/home/docker/.m2
working_dir: /usr/src/app/hello-world
ports:
- "3000:3000"
cljslein:
<<: *defaults
ports:
- "9000:9000"
Docker Composeからcljsleinサービスを実行します。
$ docker-compose run --rm --service-ports cljslein trampoline cljsbuild repl-rhino
Running Rhino-based ClojureScript REPL.
...
Retrieving org/hamcrest/hamcrest-core/1.1/hamcrest-core-1.1.jar from central
Retrieving org/clojure/tools.reader/0.8.16/tools.reader-0.8.16.jar from central
To quit, type: :cljs/quit
ClojureScript:cljs.user>
Clojure Script REPLからJavaScriptのDate関数を呼んでみます。
ClojureScript:cljs.user> (js/Date)
#inst "2015-05-16T10:17:55.200-00:00"