190

I mounted the container with this parameter:

-v /home/test/:/home/test

Inside /home/test in the host there is a symbolic link pointing to a /mnt/ folder.

But that link, although can be seen where is pointing to, seems broken inside the container:

root@f93f72b45013:/var/www/html# cd /home/test/ 
root@f93f72b45013:/home/test# ls -lrt 
total 11956 
lrwxrwxrwx. 1 root root 40 Jul 20 15:55 file -> /mnt/mountedfile/
root@f93f72b45013:/home/test# ls -lrt file/*
ls: cannot access file/*: No such file or directory

Is that even possible to be done in docker? I am not sure if is there a way to do it.

I know I can just directly mount where the symbolic link is pointing at but I was just wondering if this is possibe.

lapinkoira
  • 8,320
  • 9
  • 51
  • 94
  • I've heard of issues mapping to a `/mnt` endpoint, which may be host-specific -- the safest thing would be to avoid it if you can. – ldg Jul 20 '16 at 16:13
  • [Not an answer] One possible way to get rid of the symbolic link mess is to use `mount --bind` or `bind -t overlay`. These are native linux kernel features and works perfectly inside containers. https://unix.stackexchange.com/a/198591/423231 If you do not have plans for merging two directories, go for the bind mounts. – pPanda_beta Apr 10 '22 at 16:37

6 Answers6

250

Symlinks are a big challenge inside docker. In your case you can mount both directories:

-v /home/test/:/home/test -v /mnt/mountedfile:/mnt/mountedfile

For symbolic links to work both inside and outside the container, they have to be absolute paths and use exactly the same names.

In general, symlinks do not work inside docker. I found this the hard way.

Kemin Zhou
  • 6,264
  • 2
  • 48
  • 56
  • What to do if I have a symbolic link made in windows. The path may be c:\ (with a drive letter, semicolon and a backslash)? – Eitan Dec 10 '18 at 12:03
  • 5
    @Eitan Leave windows and embrace linux/unix systems when you wanna work with docker – Nam G VU Feb 12 '19 at 17:46
  • Yes. I have relized that Windows works wit CIF, and NFS is only on Windows Server versions (Why that basic is only on windows servers - only because that it costs, and Microsoft wants you to pay). – Eitan Feb 12 '19 at 18:18
  • 1
    Struggled a whole day with this trying to get the Laravel storage symlink working. For `docker-compose` configuration would be like this. `volumes: [./:/var/www, ./public/storage:/var/www/public/storage]`. Here, `public/storage` is a symlink to `./storage/app/public`. Thank you for the solution! – Yan Ivanov Feb 26 '19 at 22:47
  • I am able to use symbolic links with relative paths with docker 4.2.0 and windows 10. However, symbolic links with absolute paths do not work – J.Vo Jan 18 '22 at 02:15
  • Thanks for this, helped me solve my issue. Would like to add the the ORDER in which you declare the mounts matters as well (at least for docker compose). In my case `volumes: [./web/linked_folder/:/var/www/web/linked_folder/, ./:var/www]` worked, but `volumes: [./:var/www, ./web/linked_folder/:/var/www/web/linked_folder/]` did not. Hope this helps someone. – Belac Apr 27 '23 at 13:09
33

One solution is to make Docker mount the original file, but use readlink -f which prints the file's actual location. This way, you can still reference the symlink location in your command, e.g.

docker run -it -v $(readlink -f /home/test/):/home/test/ ...

user2640621
  • 437
  • 5
  • 7
  • Not working - this results in the same missing symlinks – Ami Mahloof Nov 30 '17 at 19:51
  • On macOS: `perl -MCwd -le 'print Cwd::abs_path(shift)' "$path"` (from https://stackoverflow.com/questions/7665/how-to-resolve-symbolic-links-in-a-shell-script) – akauppi Feb 22 '19 at 20:45
  • 15
    I haven't tested it in Docker, but from playing around with readlink, it appears that this will work of /home/test/ **is** a symlink, but not if /home/test/ **contains** a symlink. – Justin Donnelly Nov 03 '19 at 19:40
  • 1
    how to put this variable into docker-compose file? – Ömer An Aug 02 '21 at 12:48
10

Hello thanks for your help In my case I was struggling activating https on my angular nginx app

docker run -p 80:80 -p 443:443 \
   --name test \
   -v /etc/letsencrypt/live/exemple.com:/etc/nginx/certs \
   -v /home/admin/nginx-default.conf:/etc/nginx/conf.d/default.conf:ro test

Does not mount links cert.pem and privkey.pem inside docker

But if I use all file path explicitly like that

docker run -p 80:80 -p 443:443 \
   --name test \
   -v /etc/letsencrypt/live/example.com/cert.pem:/etc/nginx/certs/cert.pem \
   -v /etc/letsencrypt/live/example.com/privkey.pem:/etc/nginx/certs/privkey.pem \
   -v /home/admin/nginx-default.conf:/etc/nginx/conf.d/default.conf:ro test

Everything worked I suppose you could do it exactly the same thing with docker-compose

Pavel Niedoba
  • 1,554
  • 2
  • 19
  • 36
ScorprocS
  • 287
  • 3
  • 14
  • Same here if i mount the entire directory docker cannot read symlink, i have to link each pem file in docker-compose yml – Marc Guillem Jun 14 '22 at 15:50
3

It's doable but you must "think container" if you have symlinks to random files in random locations, then it's actually may not be worth it.

But consider this working worth scenario:

You have 2 folders, one with real files, and one with symlinks to real:

/static-data/
|_ data-file1.dat
|_ data-file2.dat
|
|__index/
   |_a.txt
   |_b.txt

/other/
|_ data-file1.dat -> /static-data/data-file1.dat 
|_ data-file2.dat -> /static-data/data-file2.dat 
|
|__index/
   |_a.txt
   |_b.txt

Now if you mount /other:/data

for a container when you ls -lah /data you'll see broken links because /static-data doesn't exist in the container. The solution is to create broken links in the Host, assuming /other is not directly important to host to be broken so your new structure would be:

/other/
|_ data-file1.dat -> /mirror/data-file1.dat 
|_ data-file2.dat -> /mirror/data-file2.dat 
|
|__index/
   |_a.txt
   |_b.txt

You then need 2 mount records

/other:/data
/static-data:/mirror

Now when you run a container, the symlinks that are broken for Host, are not broken in the container so /data/data-file1.dat -> /mirror/data-file1.dat and container has mounted /mirror thus the symlink is pointing to /static-data/data-file1.dat from the host

If you don't want broken symlinks in the host then you could mount both directories as

/other:/data
/static-data:/static-data

Now the links can be valid in Host and the container. As you can see this is possible, I tested that and it works, but it's worth only for obvious clusters of files. If it's all random, the you would end-up mounting a lot of dirs or maybe single files, to reflect Host structure in the container

Pawel Cioch
  • 2,895
  • 1
  • 30
  • 29
2

I can´t reply the previows answer but on a similar scenario where I need to get a linked file, setting up complete file path as you suggested on compose file worked out for me:

  - /opt/cert/ssl/live/example.com/cert.pem:/certs/cert.pem
  - /opt/cert/ssl/live/example.com/privkey.pem:/certs/privkey.pem

Files cert.pem and privkey.pem under example.com are both links to the files where certbot locates them.

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 22 '22 at 02:34
0

I think a good method to this issue.

In docker container, a symlink mounted from host cannot work properly. But a symlink created inside docker container work just fine. So, it is a good idea to mount the root (with absolute path) of interest into container first and then create symlink inside container with structures that satisfies ones' need. In this way, you are good to go.

Hope this helps.

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 28 '22 at 11:38