おれのにっき

何か問題でも

例えば、dotfilesをDockerイメージにする

f:id:windyakin:20170618180747p:plain

かねてより自分のシェルに関する環境設定を dotfiles として GitHub 上に公開することがベストプラクティスとして様々な人が行っていて、自分もそれを実践している一人である。

github.com

確かに dotfiles と GitHub による運用は便利だ。しかしながら dotfiles をある程度運用していくとほぼ必ず突き当たるであろう1つの課題がある。それは「クリーンな環境に適応するときにどうするか」だ。既に dotfiles を運用しているのであれば git pull すれば適応されるが、新しく用意した環境に対して自身の dotfiles を適用したい時どのような手順を踏んでいるだろうか。まさか初回インストールの度に各ファイルに対してシンボリックリンクを貼っていくといった単純な作業をしたいとは思わない。

その解決手段として、私はインストールのためのシェルスクリプトを書いて dotfiles に配置している。「私は」なんて偉そうなことを書いたが、だいたいこの問題に突き当たった人であれば同じような解決方法を考えるだろうと思う。シェルスクリプトは若干面倒ではあるが、基本的にはどのような環境でも動くはずであるし、追加ライブラリのインストールなんかもシェルスクリプト内に書けばその後の作業なんかも手間が省けるかもしれない。

というわけでシェルスクリプトを用意すれば初回インストールも完璧である。めでたしめでたし。

…ともいかない。新たな問題として「初回インストール用のシェルスクリプトデバッグ&テストする環境を用意する」という必要が出てきた。適当に書いたシェルスクリプトで「まあ動くだろう」と思っていたら、初期環境ならではの思わぬバグが潜んでいていざというときに使えないとか、そういう事態はできれば避けたいからだ。

まさか今使っているホストマシンを使ってテストするなんてことはやりたくないし、かといってそのテストのためだけに仮想マシンをいちいち用意するなんてこともやりたくない。

自由に使い捨てできる環境があればなぁ…

……そうか Docker だ。

dotfiles の作業環境を用意する

今回目指す最終形としては dotfiles やそのほか必要なソフトウェアをインストールしたイメージをつくって、自分の環境のコンテナを一発で建てる所であるが、まずは本来の目的である「初回インストール用のシェルスクリプトデバッグ&テストする環境を用意する」ための Docker イメージを用意しよう。

学生時代は CentOS をよく使っていたのだが、仕事では Ubuntu を使っているので、ベースを ubuntu:xenial として以下の Dockerfile を書いた。

Ubuntu 16.04 Japanized Container

やっていることとしては、apt-get で使うミラーを日本のものにしたり、最低限入れるべきなツール郡を apt-get でインストールしたり。他にも、通常コンテナ上には root ユーザしか作られないが、別途コンテナ内に管理者権限を持たないユーザを用意するのと、タイムゾーンJST にして作業をしやすくしている。ちまちまと書いたがこのぐらいだと Docker Hub を検索すればどっかに転がってるのかもしれない。

docker build --tag dotfiles_base:latest --build-arg {user_name} .
docker run -it -v ~/dotfiles:/home/{user_name}/dotfiles:ro dotfiles_base

起動時にホストマシンの dotfiles をマウントしておけば、実際にシェルスクリプトを動かして発見したバグについてもホストマシン上から修正してすぐに試することができる*1。もし環境が既に汚れているのであればコンテナを捨てて、もう一度立て直せば良い。

実際に自分がやっても動くと思っていたような箇所が実は動かなかったみたいな部分や、しょうもないバグがあったりとか、まっさらな環境から構築するからこそわかる部分が多かった。

さて、シェルスクリプトがいい感じに動くことが確認できたら、今度はそのシェルスクリプトを実行する行を Dockerfile に追記して dotfiles イメージの完成である。

なんやかんや試行錯誤した結果自分の dotfiles/Dockerfile は以下のようになった。

windyakin/dotfiles Dockerfile

個人的な事情であるが、作業効率化のためのユーティリティ類を入れる時は LinuxBrew を使っているため、コンテナ内で使うため、 LinuxBrew を入れるステップも追加している。

利点1. セットアップスクリプトのメンテナンスする時に楽

まあ今回 Docker 化することになった理由であり、得られたメリットである。今回やってはいないのだが、やりようによっては CI とか回せるかもしれない*2

利点2. 他人の dotfiles も気軽に試せる

dotfiles が公開されていてもどういう風に便利かなんてのは実際に使ってみないことにはわからない。かといってそのためにわざわざ自分の環境を壊してまで作業はしたくないし、ましてや仮想マシンを(ry

しかし Docker Hub にイメージを用意していたらどうだろう。他人の環境がたったワン・コマンドで用意できてしまう。試し飽きたらコンテナごとポイすればいい。起動時に --rm オプションを付けておくのも有効だ。

ちなみに私の環境も恥ずかしながら Docker Hub に公開しているのでワン・コマンドで実行できる。

https://hub.docker.com/r/windyakin/dotfiles/

docker run --rm -it windyakin/dotfiles

欠点1. macOS 環境は Docker で用意できない

やはり利点ばかりではない。

利点1に挙げたセットアップスクリプトのテストだが、もしそのシェルスクリプトの中で macOS だけでしか使えない仕組みを使っていると途端に動かなくなってしまう。

Homebrew については LinuxBrew によって代替が効くが、 Homebrew-Cask については Linux で代替できる仕組みは用意されていないのでどうしようもない。

欠点2. メンテナンスコストの増大

やはりやることが増えるというのは面倒である。特に dotfiles なんてのは個人環境で動きさえしてればいいので、初期のセットアップがうまくいかなくなったとしても、問題としては小さなものかもしれない。

まとめ

私の .vimrc が定まらないので、色んな人の Vim 環境を参考にするためにも dotfiles を Docker イメージ化するのが流行ってほしい。

*1:Read only にしてコンテナ上からdotfiles内を触れないようにしているのはファイル権限の問題がややこしくなるのを避けるため

*2:何をテストするんだ…