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
上でB
とC
が並列に実行されるイメージだ.
注意点
A
とB
のディストロが異なるとき
バイナリ互換?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
上の/piyoB
がA
上の/piyoA
を経由してC
上の/nyan
と共有される.