15

I want to make a folder on my host machine available during a RUN statement. That is, similar to the effect of a container run with -v:

docker run -v /path/on/host:/path/in/container mycontainer:tag

In the container this gives me /path/in/container with all files/folder in path/on/host.

To this end I am trying the experimental mount options from https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/experimental.md:

RUN --mount=type=bind,target=/path/on/host

This gives me a folder /path/on/host during the RUN.

I then have two problems:

  1. I can ls files inside /path/on/host, but not use them (e.g. cat them). I have tried changing type to e.g. cache and using source like in https://devops.stackexchange.com/questions/6078/in-a-dockerfile-is-there-a-way-to-avoid-copying-files-to-make-them-accessible-t, but I cannot make it work.

  2. I cannot figure out how to have a different path inside the "RUN image", that is, /path/in/container instead of /path/on/host.

robertdj
  • 909
  • 1
  • 5
  • 10

1 Answers1

38

I think you have misunderstood what the RUN --mount=type=bind... syntax is for. From the documentation:

This mount type allows binding directories (read-only) in the context or in an image to the build container.

In other words, this does not permit you to access arbitrary host directories in the build stage. It is not an analog to the -v command line option on docker run. It only permits you to:

  • Mount directories from your build context, or
  • Mount directories from another stage in a multi-stage build

So for example I can do this do mount a directory from one build stage into a subsequent build stage:

# syntax=docker/dockerfile:experimental

FROM centos AS centos

FROM alpine
RUN --mount=type=bind,from=centos,source=/,target=/centos ls /centos > /root/centos.txt

Or if I have a directory named example in my build context, I can do this to mount it during the build process:

# syntax=docker/dockerfile:experimental

FROM centos AS centos

FROM alpine
RUN --mount=type=bind,source=example,target=/data cp /data/* /root/

The syntax you're using (with no from specified)...

RUN --mount=type=bind,target=/path/on/host

...simply mounts the root of your build context on /path/on/host inside the container. Remember that target specifies the mountpoint inside the container. E.g., if my build context looks like this:

.
├── Dockerfile
└── example
    └── README.md

And example/README.md contains:

This is a test.

And the Dockerfile contains a RUN option similar to what you're using:

# syntax=docker/dockerfile:experimental

FROM centos AS centos

FROM alpine
RUN --mount=type=bind,target=/data cat /data/example/README.md > /root/README.md

Then when the image is built, /root/README.md has the contents of example/README.md.

larsks
  • 277,717
  • 41
  • 399
  • 399
  • 1
    You are right -- I had misunderstood the docs. Thanks for clarifying! I suppose there no way of doing the mount I am looking for? – robertdj Jan 05 '20 at 18:38
  • 1
    Hi, thank you so much for clarifying the feature and documentation ! In my case I had issues with the `source`, I missed that source was relative to the context hence I got `failed to compute cache key: "/Users/bric3/opensource/panama-foreign" not found: not found`. By the way `# syntax=docker/dockerfile:experimental` is not anymore necessary in recent docker versions. – bric3 Feb 15 '21 at 11:18
  • Doesn't `docker build -v ...` work for you during the Dockerfile build? Seems to me that it would work. – djangofan Oct 09 '21 at 00:19
  • 1
    At least according to the man page and `docker build --help`, there is no `-v` option to `docker build`. – larsks Oct 11 '21 at 22:37
  • Thanks @larsks, I had understood "This mount type allows binding directories (read-only) in the context or in an image to the build container" (https://docs.docker.com/engine/reference/builder/#run---mounttypebind) to mean any image but it actually means other images within your multi-stage build right? – We'll See Nov 11 '22 at 16:28
  • I wanted to do the same but came up on this limitation to mount only within the host build context. My solution is to run a script that does the build. At the beginning of the script I bind mount (bindfs) what I need in the context then I can then mount it in the build container per this answer, then unmount it afterwards. Alternately you can rsync a folder into the context and delete it after the build. Both ways work for me. – DKebler Apr 05 '23 at 14:57
  • 1
    It might be worth mentioning that docker supports multiple build-contexts from the host using the `--build-context flag`: https://www.docker.com/blog/dockerfiles-now-support-multiple-build-contexts/. So you should be able to specify any host dir you want to mount as a separate `--build-context` and then use that. For example `docker build --build-context mydir=/myhostdir` and then in the Dockerfile do `RUN --mount=type=bind,from=mydir,target/whatever`. – Jonas Kello Aug 28 '23 at 06:10