Docker inside docker: file missing

212 Views Asked by At

I am launching docker inside another docker container and I'm trying to make files visible inside "deepest" container.

My first container is build on python:3.8-slim image, entrypoint is ["python"] and is called test-client.

I launch it as docker run --rm -it -v /home/.../inputs:/inputs -v /var/run/docker.sock:/var/run/docker.sock --network ... test-client start_client.py ....

Now inner container. Inside start_client.py I run it with docker==5.0.3 library.

def check_docker():
    import time
    inputs = Mount('/inputs', 'inputs')
    client = docker.from_env()
    client.images.pull('apline')
    time.sleep(30) # I will explain this later
    output = client.containers.run(
        'apline', 'ls inputs -al',
         mounts=[inputs]
    ).decode('utf-8')
    for line in output.split('\n'):
        print(line)

So. I used time.sleep to have time to dive into first container and check if needed file is presed. Yes it is, my file is inside first container. But output of deepest container sees no files inside inputs directory.

What am I doing wrong?

1

There are 1 best solutions below

0
On

You can't directly mount a directory from one container to another. In the mounts option you show (and in docker run -v and Compose volumes:) the host path is always a path on the system where the Docker daemon is running. If you're bind-mounting the host's Docker socket, these paths will be paths on the host; if $DOCKER_HOST points into a VM or at a remote machine, the paths will be paths on that system and not your local one.

But, in your specific example, the directory you're trying to remount is already a mount itself. If you mount the same host location into both containers, then you'll be able to see the files. I'd suggest specifying this in an environment variable

inputs = Mount('/inputs', os.getenv('INPUT_SOURCE', 'input'))

and when you run the container, pass that directory in as a variable

INPUT_SOURCE="$PWD/inputs"
docker run --rm -it \
  -e INPUT_SOURCE \
  -v "$INPUT_SOURCE:/inputs" \
  --network ... \
  test-client \
  start_client.py ...

If you use a bare string input in the Mount object as you've done, it will mount (and automatically create) a named volume. You can use your container to inspect this

docker run --rm -v inputs:/inputs test-client \
  -e 'print(os.listdir("/inputs"))'

(you can use a simpler shell syntax if you remove the ENTRYPOINT ["python"] line from your Dockerfile).