Common Lisp開発環境 on Docker
Docker上でCommon Lisp開発環境(by Emacs+SLIME)を起こしてみました。何が入っているか分からない開発環境だとどうしてもアップデートが億劫になるので、その辺をきっちりコード化したかったというのが動機です。
どちらかと言うとAnsibleやChefのように直接サーバを設定するタイプの方がこの用途ではスタンダードな気がします(単なる印象)が、Dockerの方が試行錯誤で出るゴミ*1が残らないので好みでした。
注意点
執筆時点(2016/08/11)では、CentOS 7のyumではDocker 1.10が入りますが、事実上1.11以上が必須です。1.10ではEmacsの描画が激しく崩れるという問題があるためです(参考の前回記事:Dockerを1.10から1.11へアップデート on CentOS7 - eshamster’s diary)。
また、Dockerfileからビルドする場合にも必要な可能性があります。Emacsのビルド部分で詰まる可能性があるためです(参考の前々回記事:Docker上のEmacsのビルドでハマった話 - eshamster’s diary)。どういう訳か1.11.2では参考記事の問題は起きていないので、1.11にしておくとスムーズ…かもしれません*2。
概説
まずは作ったものへの諸リンク*3。
- DockerHub: https://hub.docker.com/r/eshamster/cl-devel/
- GitHub: https://github.com/eshamster/docker-cl-devel
元々は以前書いた記事「Common Lisp開発環境を新規に作ったのでメモ - eshamster’s diary」をそのまま再現してCentOS 6ベースで作った(1.0~1.3)のですが、Clozure CLの最新版が入らないなど問題しかないので、CentOS 7をベースに作り直しました(2.0~)。やっていることは変わらないので気になった部分だけメモ。
- CentOS 7化周りの話
- 一番困った点はw3mのインストール(emacsからのHyperSpec閲覧用)です。標準リポジトリからなくなったので、ソースからビルドが必要ですが、単純にはできません。「[CentOS7] emacs24にemacs-w3mインストール - Qiita」にあるように細工が必要です
- もうサポートしないということかと思うので、移行先を探すのが正道ですかね…
- roswellのビルドには標準リポジトリのautoconfで十分でした
- roswellのバージョンを固定した方がいいか迷いどころですが、適宜最新化しながら使う予定なので都度対応で良いかなと
- Emacsは24系であればいいので、CentOS 7ならyumでいいはず…と思っていたら、yumで入る24.3では動かないEmacs拡張(どれかは忘れました)がありました。そのため、結局ソースから24.5を入れました
- 一番困った点はw3mのインストール(emacsからのHyperSpec閲覧用)です。標準リポジトリからなくなったので、ソースからビルドが必要ですが、単純にはできません。「[CentOS7] emacs24にemacs-w3mインストール - Qiita」にあるように細工が必要です
- その他の話
実際に使うとき
実際に開発に利用する上ではeshamster/cl-develだけでは不足です。GitHubにpushするためのSSH鍵の設定や、コンテナ終了後もデータを残すためのボリュームの設定等が必要です。とはいえ、こうしたパーソナルな設定を公開Dockerfileに書くのも違う気がします。
そのため、下記の3ファイル(Dockerfile, 設定ファイルのsetenv, 起動用のrun.sh)とSSH鍵*4を用意し、run.shを叩いてコンテナを起こしています。なお、ホストのマウント先に指定した${HOME}/work/lisp
は事前にchown -R 1000:1000 ${HOME}/work/lisp
*5と所有者設定をしておかないとゲスト側から触れません。
run.shでコンテナを起動した後は、emacsを立ち上げ*6、M-x slime
ですぐにslimeが使えます。保存の必要なものは~/work/lisp
以下に保存します。また、コンテナをdetach*7した後は、docker attach cl
で再接続できます(プロセス名cl
はsetenv
で設定)。
- Dockerfile
FROM eshamster/cl-devel:2.0 # --- git settings --- # RUN git config --global user.name "<ユーザ名>" && \ git config --global user.email "<メールアドレス>" # --- ssh settings --- # ARG user=dev ARG SSH_HOME=/home/${user}/.ssh RUN mkdir ${SSH_HOME} && \ chmod 700 ${SSH_HOME} USER root COPY id_rsa ${SSH_HOME} COPY id_rsa.pub ${SSH_HOME} RUN chown ${user}:${user} ${SSH_HOME}/* && \ chmod 600 ${SSH_HOME}/* # --- other settings --- # USER ${user} RUN ros install prove RUN echo "export PATH=${HOME}/.roswell/bin:${PATH}" >> ${HOME}/.bashrc RUN echo "export LANG=ja_JP.UTF-8" >> ${HOME}/.bashrc
- 設定ファイル(setenv)*8
export HOST_PORT=17380 export GUEST_PORT=18616 export RUN_NAME=cl
- 起動用シェル(run.sh)
#!/bin/bash set -eu . "${1:-$(dirname ${0})/setenv}" docker rmi $(docker images | awk '/^<none>/ { print $3 }') || echo "ignore rmi error" docker rm `docker ps -a -q` || echo "ignore rm error" docker build -t cl . docker run --name=${RUN_NAME} -p ${HOST_PORT}:${GUEST_PORT} -e "OPEN_PORT=${GUEST_PORT}" -e "HOST_PORT=${HOST_PORT}" -v ${HOME}/work/lisp:/home/dev/work/lisp -it cl /bin/bash
感想
上記の環境が整ってしまえば、後はrun.shをたたくだけで簡単にフレッシュな環境が得られるので良い感じです(気づいたら環境が壊れて色々動かなくなった…となってもすぐ戻せますし)。しばらく使ってみましたが、Dockerを1.11にアップデートしてEmacsの描画問題が解決してからは快適に利用できています。
後続の関連記事
*1:実はそのゴミ(だと思っていたもの)のおかげで動いていたとか、設定に書いていない元々入っていたもののおかげで動いていたとか、心配性なのでその辺りがどうしても気になります…
*2:曖昧な言い方になっているのは、きちんと調査できていないためです。本当に1.11にアップデートしたことで解消されたのか半信半疑です…
*3:DocekrHubとGitHubの連係機能を後から知ったので連係できていないという…。後からできるのでしょうか
*4:.pubの方は必須ではないですが、一緒に持っておかないと対応が分からなくなりそうなので…
*5:設定すべきID(ここでは1000番)はゲスト側で/etc/passswdを見れば確認できます
*6:最初からrun.shで/usr/bin/emacsを立ち上げても良い気がします。Emacsの走る環境も触れた方が良いかと思い、/bin/bashで立ち上げています
*7:なお、Dockerの初期設定ではdetachがCtrl-P Ctrl-Qという正気とは思えないキーバインドになっているので、「docker-1.10.0からデタッチキーが変更できるようになった - Qiita」あたりを参考に変更しましょう。Ctrl-Pはないよなあ…
*8:portの設定は必須ではないですが、Webアプリケーションを開発するような想定でつけています。ゲスト側ではGUEST_PORTで接続を待ち受け、つなぐ側はホストのHOST_PORTに繋ぎます