Clojure + Emacsな開発環境を作った on Docker
前回記事「Common Lisp開発環境 on Dockerの現状 - eshamster’s diary」の冒頭で少し書いていたように、Clojure開発用のDocker環境を作ってみました。そろそろいい加減にClojureScriptをいじってみようかというのが主な動機です。
Docker上に開発環境を起こすのはCommon Lispに続いてようやく2言語目なので、言語ごとの開発環境を量産するための知見(主にEmacsの設定をどう管理するか)を得るという副目標もあります。
先に完成品のリンクを貼っておきます。
目次
概要
次のような構成を目指します。
- Alpine Linux:軽量なLinux
- Leiningen:Clojureプロジェクトの色々な管理をするソフト(Node.jsで言うnpmのような位置付け)
- Emacs
1, 2に関しては公式のDockerイメージが提供されているので、DockerfileでFROM clojure:lein-2.8.1-alpine
のようにするだけです。
3のEmacsの設定については下記を参考…というよりClojure部分についてはほぼそのままです。
そんなわけなので、正直余り書くこともなかったりします…。
Dockerfile
Dockerfileの記述ですが、上記の通りClojure (Leiningen) の設定については公式リポジトリからFROMするだけですし、Emacsについてもapkの標準リポジトリからとってくるだけで新しいもの(現在はバージョン25.3.1でした)がとれますし、特筆すべき点がないです…。
FROM clojure:lein-2.8.1-alpine RUN apk update --no-cache RUN apk add --no-cache emacs git # --- install wget with certificate --- # RUN apk add --no-cache ca-certificates wget openssh && \ update-ca-certificates # --- user settings --- # ARG emacs_home=/root/.emacs.d ARG site_lisp=${emacs_home}/site-lisp ARG dev_dir=/root/work RUN mkdir ${emacs_home} && \ mkdir ${site_lisp} && \ mkdir ${dev_dir} # --- run emacs for installing packages --- # COPY init.el ${emacs_home} RUN emacs --batch --load ${emacs_home}/init.el # --- miscs --- # WORKDIR /root
Emacsの設定
設定自体について
前述のようにClojure部分の設定については、ほぼ「新: Emacs を使うモダンな Clojure 開発環境 - Qiita」のままです。最低限使いそうなところだけピックアップして言った感じなので、差異や不足のある部分には大して意味はありません。意図的に変えたのは下記程度です(細かい話ですが…)。
company-mode
(auto-complete
の代替)のキーバインド- 個人的には
M-p
,M-n
での候補選択に慣れているので、C-p
,C-n
への割り当てはしていません - 個人的には
C-i
はデフォルトの用途で頻繁に利用するので、候補の強制呼び出しのキーバインドは代わりにC-c C-i
としました
- 個人的には
RainbowDelimiters
- 記事中にも「そこまでの効果はない」とありますが、実際昔使ってみたときに嬉しさを感じられなかったので外しました
全体は少し長いので現時点の設定へのリンクだけ貼っておきます。88行目の;; ----- Clojure ----- ;;
というコメント以降("auto settings"以降を除く)がClojure関連の設定になります。
https://github.com/eshamster/docker-clj-devel/blob/a3addf8c5dd58d1f2b6fbbd08a75b54aad4a9071/init.el
言語別環境の量産に向けた簡単な考察
さて、Common Lisp用環境を作るときは余り意識していませんでしたが、今回init.el
の中で、共通設定*1とClojureの設定を分離しています(前述のように88行目前後が分かれ目)。もう少し踏み込んで、言語別のDocker環境(用のEmacs設定)を管理するためには下記のようにするのが良さそうだというのが今の考えです(実際やってみると変わりそうですが)。
- Emacs設定ファイル側
- 共通設定と言語別設定を別ファイルに分ける
- これらのロードには
init-loader
(るびきちさんの紹介記事リンク)を利用するinit.el
自体を触ることなく、特定の場所に(特定の形式で)追加の設定ファイルを置くだけで読み込み対象を変えられる、というのはDockerfileの記述と相性が良さそうです
- これらはDockerfile用リポジトリとは独立したリポジトリ上で管理する
- 複数言語を同時に利用するような環境が欲しくなった場合のことを考えると、共通設定だけでなく言語別設定もまとめて管理した方が良さそうです
- Dockerfile周辺側
実際に使うとき
実際に開発環境として利用する際にはもう少しローカルな設定が必要になりますが、これこそ以前書いたCommon Lisp用環境記事の同名の章と変わらないので、ポイントのコピペとファイルの貼り付けだけで終わりにします*2。
- ポイント
Dockerfile
: ※横に利用するSSH鍵を置いておくこと
FROM eshamster/clj-devel:latest # --- git settings --- # RUN git config --global user.name "eshamster" && \ git config --global user.email "hamgoostar@gmail.com" # --- ssh settings --- # ARG user=root ARG SSH_HOME=/root/.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}/* # --- --- # USER ${user} RUN echo "export LANG=ja_JP.UTF-8" >> ${HOME}/.bashrc RUN apk add --no-cache openssl-dev
setenv
export HOST_PORT=17381 export GUEST_PORT=18616 export RUN_NAME=clj export VOLUME=${HOME}/work/clojure
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" name="clj_web_devel" docker build -t ${name} . docker run --name=${RUN_NAME} -p ${HOST_PORT}:${GUEST_PORT} \ -e "OPEN_PORT=${GUEST_PORT}" \ -e "HOST_PORT=${HOST_PORT}" \ -v ${VOLUME}:/root/work \ -it ${name} /bin/sh
*1:Common Lisp環境のものと実質は同じですが、use-packageを使ってリファクタリングしました
*2:これはこれでリポジトリ起こして管理した方が良いのだろうとは思っています。ただ、今回のように「(DBなしの)Web開発用の最低限の設定」程度であれば共通化できるのですが、例えば、PostgreSQLを使う環境用、Redisを使う環境用…と個別のアプリ向け設定が必要になってきたときにどう管理すべきか考えられてないので足踏みしてます