Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why docker in docker (dind) containers mount volumes with host path?

I have a setup with docker in docker and try to mount folders.

Let's say I have those folders that I wish to share with his parent. On the host, I created a file in /tmp/dind called foo. Host starts container 1, which starts container 2. This is the result I want to have.

Host      | Container 1 | Container 2

/tmp/dind |  /tmp/dind2 | /tmp/dind3
      <------->     <------->

Instead, I get

Host      | Container 1 | Container 2

/tmp/dind |  /tmp/dind2 | /tmp/dind3
      <------->
      <----------------------->

Code here:

docker run --rm -it \
  -v /tmp/dind:/tmp/dind2 \
  -v /var/run/docker.sock:/var/run/docker.sock docker sh -c \
    "docker run --rm -it \
      -v /tmp/dind2:/tmp/dind3 \
      -v /var/run/docker.sock:/var/run/docker.sock \
      docker ls /tmp/dind3"

This outputs nothing, while the next command gives foo as result. I changed the mounted volume:

docker run --rm -it \
  -v /tmp/dind:/tmp/dind2 \
  -v /var/run/docker.sock:/var/run/docker.sock docker sh -c \
    "docker run --rm -it \
      -v /tmp/dind:/tmp/dind3 \
      -v /var/run/docker.sock:/var/run/docker.sock \
      docker ls /tmp/dind3"

The question is, what do I need to do in order to use Container 1 path and not host? Or do I misunderstand something about docker here?

like image 679
David Bensoussan Avatar asked Nov 29 '18 13:11

David Bensoussan


1 Answers

For all that you say “Docker-in-Docker” and “dind”, this setup isn’t actually Docker-in-Docker: your container1 is giving instructions to the host’s Docker daemon that affect container2.

Host      Container1
    /-----
 (Docker)
    |     Container2
    \---->

(NB: this is generally the recommended path for CI-type setups. “Docker-in-Docker” generally means container1 is running its own, separate, Docker daemon, which tends to not be recommended.)

Since container1 is giving instructions to the host’s Docker, and the host’s Docker is launching container2, any docker run -v paths are always the host’s paths. Unless you know that some specific directory has already been mounted into your container, it’s hard to share files with “sub-containers”.

One way to get around this is to assert that there is a shared path of some sort:

docker run \
  -v $PWD/exchange:/exchange \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e EXCHANGE_PATH=$PWD/exchange \
  --name container1
  ...

# from within container1
mkdir $EXCHANGE_PATH/container2
echo hello world > $EXCHANGE_PATH/container2/file.txt
docker run \
  -v $EXCHANGE_PATH/container2:/data
  --name container2
  ...

When I’ve done this in the past (for a test setup that wanted to launch helper containers) I’ve used a painstaking docker create, docker cp, docker start, docker cp, Docker rm sequence. That’s extremely manual, but it has the advantage that the “local” side of a docker cp is always the current filesystem context even if you’re talking to the host’s Docker daemon from within a container.

like image 99
David Maze Avatar answered Sep 30 '22 14:09

David Maze