36

I have two Dart applications I need to dockerize. These two apps use a shared source directory.
Because Docker prevents adding files from folders outside the context directory (project/app1) I can't add files from ../shared nor from shared (the symlink inside projects/app1).

I'm looking for a way to trick Docker to do it anyway.

My simplified project structure

- projects
  - app1
   - Dockerfile
   - shared (symlink ../shared)
   - otherSource
  - app2
   - Dockerfile
   - shared (symlink ../shared)
   - otherSource
  - shared
    - source

I could move Dockerfile one level up and run docker build from there but then I need two Dockerfiles (for app1 and app2) in the same directory.

My current idea was, if I could somehow hide the fact that projects/app1/shared is a symlink this problem would be solved. I checked if I can share projects using Samba and remount it somewhere else and configure Samba to treat symlinks like normal folders but haven't found whether this is supported (I have not much experience with Samba and not tried it yet, just searched a bit).

Is there any other tool or trick that would allow that?

I would rather not change the directory structure because this would cause other troubles and also rather not copy files around.

34

I don't have much experience with docker so I can't promise this will work but one choice would be to mount the directory instead of linking to it:

$ cd projects/app1
$ mkdir shared
$ sudo mount -o bind ../shared shared/

That will attach ../shared to ./shared and should be completely transparent to the system. As explained in man mount:

The bind mounts.

Since Linux 2.4.0 it is possible to remount part of the file hierarchy somewhere else. The call is:

mount --bind olddir newdir

or by using this fstab entry:

/olddir /newdir none bind

After this call the same contents are accessible in two places.

  • 1
    @zoechi this is perfectly on topic on both sites. As a general rule, I would post more technical questions like this on U&L and more user-space questions here. The choice is completely up to you though. On the one hand, there are more users here so more eyeballs, on the other, there is a much higher concentration of professional *nix people on U&L. Just make sure you don't post the same question on both sites. If you want to move it, either delete this or flag for mod attention and ask them to migrate. – terdon Nov 20 '14 at 13:05
  • 2
    It was mandatory for me to restart docker daemon! Else the mounted dir was not visible in the container. – dim Jan 22 '16 at 11:25
  • @dim yes! I tried to get it to work with Capistrano and it didn't work – turns out I mounted the shared directories after I started the container – csch Nov 7 '16 at 14:18
  • Unfortunately this won't work for Windows or OS X users. The debate about this issue has been... lively. – Jason Feb 24 '17 at 1:34
  • is mounting 'commited' to source control eg github? or would I have to do it every time? – pie6k Mar 14 at 11:22
21

This issue has come up repeatedly in the Docker community. It basically violates the requirement that a Dockerfile be repeatable if you run it or I run it. So I wouldn't expect this ability, as described in this ticket: Dockerfile ADD command does not follow symlinks on host #1676.

So you have to conceive of a different approach. If you look at this issue: ADD to support symlinks in the argument #6094, a friend of ours from U&L (@Patrick aka. phemmer) provides a clever workaround.

$ tar -czh . | docker build -

This tells tar to dereference the symbolic links from the current directory, and then pipe them all to the docker build - command.

excerpt from tar man page
-c, --create
       create a new archive

-h, --dereference
       follow symlinks; archive and dump the files they point to

-z, --gzip, --gunzip --ungzip
  • 3
    This is an EXCELLENT solution! I understand why Docker claims they want to omit this feature. However, there is a considerable difference in the workflow I use while developing my containerize project and how I expect it to be built for production. On my local machine I want a super tight feedback loop. My app has 1 git repo and the build environment for the containers has a 2nd repo. I need to be able to make edits and build tests locally before I can decide if I want to commit and push. I won't have symlinks or ADD instructions in my final project. – Bruno Bronosky Mar 16 '15 at 18:44
  • 5
    Dockerfiles are not repeatable. Dockerfiles can not possibly be made repeatable, because they almost all have apt-get or something equivalent at the 2nd or 3rd layer and apt-get is not repeatable. Tying the Docker development strategy to a misguided attempt to make the impossible true will just saddle Docker with a series of bad abstractions that help nobody. nathanleclaire.com/blog/2014/09/29/… – Jason Feb 24 '17 at 1:12
  • 1
    Ok, so I don't really see why this is any better than a cp command, can you explain why it's better? I also think the pipe is confusing/overly convoluted. Why not just put the tar command above the build command. I guess because then you would overwrite the symlinked dir with the real dir. – Alexander Mills Jul 14 '17 at 21:13
  • 1
    @AlexanderMills - best way to see what happens is to try it and see the difference. Also the above is a building of a container not a running, so there's no mounting. stackoverflow.com/questions/37328370/…. I highly suggest you try all these things out, it'll make much more sense. – slm Jul 15 '17 at 2:31
  • 1
    I just added /bin/cp ../requirements.txt . && docker build ... to a Makefile for building the Docker, it was easier – user5359531 Jan 10 '18 at 20:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.