Docker outside of Docker (DooD) & bind-mount で詰まった話 (原因解明済、未解決)

Docker開発環境

経緯

  • GitLab private instanceを使っている案件にアサインした
  • CIを構築するも、ランナー上でdockerを動かしたとき、bind-mountが意図通り動作しない

    • 中身のあるディレクトリをマウントしたはずなのに、コンテナからは見えない

再現

ランナー相当のDooD構築

  • ホストのdockerdのバージョンをまず調べる
host:~$ docker --version
Docker version 18.09.7, build 2d0083d
  • コンテナ内のDockerクライアントから、コンテナ外(ホストマシン)のDockerデーモンにDocker リモートAPIを送信できるよう、ソケットをマウントする
  • ホストのdockerdとバージョンの一致するdockerイメージを使用する
host:~$ docker container run --rm -dit -v /var/run/docker.sock:/var/run/docker.sock --name runner docker:18.09
host:~$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
71e6444211ef        docker:18.09        "docker-entrypoint.s…"   3 seconds ago       Up 2 seconds                            runner
  • この時点でこういう状態:

20200110222115

  • 簡単のために、以下、ホストのDockerクライアントとRunnerコンテナのDockerデーモンを省く:

20200110222257

Runnerコンテナにログイン

host:~$ docker container exec -it runner sh
/ #
  • Runnerコンテナ内でコンテナを一覧する
docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
71e6444211ef        docker:18.09        "docker-entrypoint.s…"   5 minutes ago       Up 5 minutes                            runner
  • Runnerコンテナ自身が見えている
  • 外側(ホスト側)のDockerデーモンにDocker リモートAPIを送信できているからに他ならない

20200110222436

Runner内でコンテナ生成

# in Runner
docker container run --rm -dit alpine sh
docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
0ff3670c39c1        alpine              "sh"                     3 seconds ago       Up 2 seconds                            sad_mclean
71e6444211ef        docker:18.09        "docker-entrypoint.s…"   22 minutes ago      Up 22 minutes                           runner

20200110222519

ここまではふつう

Runner内でコンテナ生成する際、Runner内のファイルのbind-mountを試みる

  • これになりたい:

20200110222759

  • が、実際やってみるとおかしなことが起きる
  • まずRunnerコンテナ内でファイルを用意
# in Runner
mkdir /tmp/myapp
echo 'index' > /tmp/myapp/index.html
cat /tmp/myapp/index.html
index
  • bind-mountしてコンテナ生成を試みる
# in Runner
docker container run --rm -dit -v /tmp/myapp:/var/www/myapp busybox sh
41d34cf4052a...
  • ログインしてファイルを見に行くと…
#in Runner
docker container exec -it 41d34cf4052a sh

# in new container
ls /var/www/myapp -la
total 8
drwxr-xr-x    2 root     root          4096 Jan 10 13:36 .
drwxr-xr-x    1 root     root          4096 Jan 10 13:36 ..
  • ファイルがない

    • ディレクトリはある

20200110224215

  • 新しく生成されたコンテナ側の/var/www/myapp/でファイルをtouchしても、Runner側の/tmp/myapp/には反映されない。
  • mountできてないのでは…?

真相

  • ホスト側のディレクトリがマウントされてました、というオチ

    host:~$ ls /tmp/myapp -ld
drwxr-xr-x 2 root root 4096 Jan 10 22:36 /tmp/myapp

20200110223422

docker container run -v srcPath:destPath ...

srcPathは、DockerクライアントではなくDockerデーモンから見たパスである

(考えてみれば当然。相対パスが使えないのもそれが理由だろうし)

世の中ではこの問題をどうやって解決しているんだろうか…