水底

ScalaとかC#とかネットワークとか

Docker in Docker のメモ書き

「Dockerの中でDcckerを動かしたい」ということはよくあると思う. 主に2つのアプローチが存在する.

  • dind(DockerinDocker)イメージを利用
  • sockをホスト-コンテナで共有する

今回は後者を取り上げる. なお, どちらの方法もセキュリティ的にやや難ありなので注意して使う必要がある. 以降, すべてのホストをA, 通常のコンテナをB, コンテナ内から呼び出されるコンテナをCとする.

利用方法は非常にシンプル. A-B間で「sock」と「dockerコマンドそのもの」をrun時にvolume経由で共有する. 以下, 簡単なサンプル.

# on A
docker run -it -v /var/run/docker.sock:/var/run/docker.sock -v `which docker`:/bin/docker alpine sh

# on B
which docker
# => /bin/docker
docker info
# => Aのデーモンのinfoが出力される
docker ps
# => B自身が含まれたリストが出力される

A上でBCが並列に実行されるイメージだ.

注意点

ABのディストロが異なるとき

バイナリ互換?libc/glibc辺りのライブラリ不足?の関係か, 共有したはずのdockerコマンドが動かないことがある(ホストA: ubuntu, コンテナB: alpine で確認). どうしようもないので, Bに対してコマンドを個別でインストールまたはBのイメージビルド時に埋め込む必要がある. (ちなみに公式docには, 「クライアントとしてのdockerコマンドならOS Xでビルドしてもlinux上でもだいたい動くはずだぜ!」とか書いてありますが動かないものは動かない, 悲しい)

Docker in Dockerのrun時にvolumeを使うとき

B内でdockerコマンドを叩くときに -v を使ってvolume共有したいことがあると思う. このとき, :の前に記述したパスはsockの所有者, つまりAのパスとして解釈される. BのコンテンツをCと共有したい場合は一旦Aを経由させる必要がある.

以下, 上記の注意点を考慮したサンプル

# on A
docker run -it -v /var/run/docker.sock:/var/run/docker.sock -v /piyoA:/piyoB alpine sh

# on B
apk add --no-cache docker
docker run -it -v /piyoA:/nyanC alpine sh

B上の/piyoBA上の/piyoAを経由してC上の/nyanと共有される.