Common Lisp開発環境 on Dockerの現状

目次

前書き

あけましておめでとうございます。昨年は5件しか投稿していませんでしたが、今年はもっと増やす所存であります。

Clojureの開発環境をDocker上に作ったので記事にしようかと思い、1年以上前に書いたCommon Lisp + Emacs環境 on Dockerな記事を見直していたのですが、現状と合わないままになっていることに気付きました。そのままにして新しい環境について書くのも寝覚めが悪いので、アップデート状況を簡単に書きます。

何がどう変わったか

eshamster.hatenablog.com

最初にDocker上での開発環境を作った時のものが上記の記事でした。ここではCentOS7ベースで作っていました。cl-devel (DockerHub)としてDockerHubにも上げています。

eshamster.hatenablog.com

次に、上記の記事ではCommon Lispの実行環境(not 開発環境)をAlpine Linux*1ベースで作成しました。こちらはcl-baseと名付けています。

この記事で、開発環境もこの上に作り直したい…ということを言っていたのですが、現状はその通りになっています。つまり、Alpine + Common Lisp (with Roswell) + Emacs on Dockerな環境になっています。ただ、当時DockerHubに慣れていなかったばかりに、上述のcl-develGitHubとの連動ができていなかったので、下記のようにcl-devel2として新しく作っています(作成後の連携は無理そうでした)。分かりにくくなるのでよろしくないのですが、念のため元の方も残しておこうかと…。

主には以上です。以下細部ですが、以前書いたものとそれほど変更はないです。

Dockerfile

Dockerファイルをべったり貼り付けておきます。入れているものなどはCentOSベースの時と変わっていません。詳細は非Dockerな開発環境を作った「 Common Lisp開発環境を新規に作ったのでメモ - eshamster’s diary (非Docker)」で書いていたものと大体同じです。

細かな部分で目立った違いとして、apkの標準リポジトリは割と新しいEmacsが入っているので、自力でEmacsをビルドする必要がなくなった点は結構助かりました。あとは、(ソース中にもコメントしてますが)Slime 2.20がうまく動かせそうになかったため、Slime 2.19を明示的に入れていますね…。どういう環境で起きるものなのかなど、きちんと調査できてないです。

init.elは余り変わっていないので省略します。Clojure環境を作るときにいくらか整理(リファクタリング)したので、そのうち反映する…つもりです。

FROM eshamster/cl-base:2.3

RUN apk update --no-cache
RUN apk add --no-cache emacs git w3m

# --- install wget with certificate --- #

RUN apk add --no-cache ca-certificates wget openssh && \
    update-ca-certificates

# --- make work directory --- #

ARG work_dir=/tmp/work
RUN mkdir ${work_dir}

# --- user settings --- #

ARG emacs_home=/root/.emacs.d
ARG site_lisp=${emacs_home}/site-lisp
ARG emacs_docs=${emacs_home}/docs

ARG dev_dir=/root/work

RUN mkdir ${emacs_home} && \
    mkdir ${site_lisp} && \
    mkdir ${emacs_docs}

RUN ln -s ${HOME}/.roswell/local-projects ${dev_dir}

# --- install HyperSpec --- #

ARG hyperspec=HyperSpec-7-0

RUN cd ${work_dir} && \
    wget -O - ftp://ftp.lispworks.com/pub/software_tools/reference/${hyperspec}.tar.gz | tar zxf - && \
    mv HyperSpec ${emacs_docs}

# --- install slime-repl-color --- #

RUN cd ${site_lisp} && \
    wget https://raw.githubusercontent.com/deadtrickster/slime-repl-ansi-color/master/slime-repl-ansi-color.el

# --- run emacs for installing packages --- #

# In slime 2.20, slime-restart-inferior-lisp fails when using ccl-bin.
# If changing lexical-binding in slime.el to nil, it could be solved.
# But in the settings, it fails when using sbcl-bin...
# So I decided to downgrade slime to 2.19
RUN cd ${emacs_home}/site-lisp && \
    wget -O - https://github.com/slime/slime/archive/v2.19.tar.gz | tar zxf - && \
    wget -O - https://github.com/purcell/ac-slime/archive/0.8.tar.gz | tar zxf -
COPY init.el ${emacs_home}

RUN emacs --batch --load ${emacs_home}/init.el

# --- miscs --- #
WORKDIR /root

実際に使うとき

Common Lisp開発環境 on Docker - eshamster’s diary 」の同名の章からあまり変わっていないです。ポイントは下記でした。

  • gitの設定やSSH鍵のコピーなどパーソナルな設定をするためのDockerfileを作る
  • ポートやボリュームの設定をした設定ファイルを作る(setenv
  • 上記を利用して起動するためのスクリプトを作る(run.sh
    • ./run.shでコンテナをビルド・起動した後は、コンテナ内の/root/work/lispフォルダで作業します

以下、変更点だけコメントして貼り付けていきます。

Dockerfile: ベースイメージを変更した点と、よく使うものをros installしておくようにした点が主な変更です。build前に、利用するSSH鍵を横に置いてください(こちらは変更点ではないですが、念のため)。

FROM eshamster/cl-devel2:3.5B

# --- git settings --- #
RUN git config --global user.name "<ユーザ名>" && \
    git config --global user.email "<メールアドレス>"

# --- 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 ros install prove && \
    ros install qlot && \
    ros install ccl-bin && \
    ros use ccl-bin
RUN echo "export PATH=${HOME}/.roswell/bin:${PATH}" >> ${HOME}/.bashrc
RUN echo "export LANG=ja_JP.UTF-8" >> ${HOME}/.bashrc

RUN apk add --no-cache openssl-dev

setenv: VOLUMEの設定をこちらに持ってきました

export HOST_PORT=17380
export GUEST_PORT=18616
export RUN_NAME=cl
export VOLUME=${HOME}/work/lisp

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 ${VOLUME}:/root/work/lisp -it cl /bin/sh

以上です。やはり簡単に環境作り直せるのはいいですね。なんだかんだでアップデートの時は何かと引っかかってそれなりに苦労しますが…。


*1:※軽量なLinuxでDockerコンテナのベースとして広く使われています