Docker のクライアント用バイナリをビルドする

Docker はクライアントとサーバで同一のバイナリを使用する。 しかし、Docker の実行バイナリを古い Linux カーネル(CentOS 5系とか)上で実行する と、Segmentation Fault となる。 docker version とかそういう簡単なコマンドでさえ。

せめて古いカーネル上で Docker をクライアントとしてだけ動作させたい。 Docker のクライアントは docker デーモンに対して、HTTP の API 叩いているだけなので、Docker をクライアントとしてだけ動作させたければ、カーネルには依存しないはず。 そこで、DOCKER_CLIENTONLY 環境変数のフラグを立てて docker をビルドするとよい。 Mac 用のバイナリもきっとこうやって作成しているはず。

go get -v github.com/docker/docker && cd $GOPATH/src/github.com/docker/docker
git checkout release
./hack/vendor.sh
GOOS=linux GOARCH=amd64 DOCKER_CLIENTONLY=1 ./hack/make.sh dynbinary

DOCKER_CLIENTONLYについては下記のドキュメントにて発見した。

https://github.com/docker/docker/blob/release/hack/PACKAGERS.md

DOCKER_CLIENTONLY 以外にも DOCKER_BUILDTAGS を使ってグラフドライバの一部をバイナリから除外したりできるっぽい。

今のところ、Docker デーモンが起動しているホストを用意し、さらに全ホストに上記の docker クライアントバイナリを配布するようにしている。

なにがやりたいか

maakit とか percona toolkit など、様々な運用ツールを環境を整える手間なく、すぐ使いたい。もしくは使ってもらいたい。一般的なツールならまだいいけど、社内独自ツールだと環境を整えるだけでとにかくめんどくさい。

Docker デーモンとクライアントは異なるホスト間でAPI通信する前提なので、もちろん使えるツールには制約はある。 とはいえ、ツールを実行して標準出力をみたいとかだけならだいたい事足りる気がしている。 なにか成果物がクライアント側に必要な場合は、Docker コンテナ上での成果物はdocker cpコマンドで手元に持ってこれる。 もしくは Docker image 上の特定のファイルを手元に引っ張りたいだけなら nsenter が参考になる。 jpetazzo/nsenter · GitHub に書かれているインストール方法がとにかくかっこいい。

docker run --rm jpetazzo/nsenter cat /nsenter > /tmp/nsenter && chmod +x /tmp/nsenter

逆に今のところ、Docker クライアントと Docker デーモンが異なるホストにいる場合、Dockerfile の ADD でしか手元のファイルをコンテナに渡せない。(NFSとかファイルサーバを経由するとかがんばりようはある)

Moving a file from the host system to a container · Issue #905 · docker/docker · GitHub

ちょっと関係ないけど、Docker はクライアントとサーバでAPIのバージョンが等しくなければならない。 Docker 自体のバージョンが上がるとAPIのバージョンも上がる(常にAPIバージョンが上がってるかはわからない)ようで、Docker を大規模展開したあとのバージョンアップがちょっとめんどくさそう。