Reputation: 85
I want to share single files between docker containers
ContainerA:
- file-1
- file-2
- file-3
- shared-file
ContainerB
- file-a
- file-b
- file-c
- shared-file
It is not possible to share a complete volume for me. The path in the container is not the same.
Upvotes: 5
Views: 2293
Reputation: 729
If containerA creates a file at a certain path and overwrites symlinks I don't think it's possible to do this with a "clean" approach (otherwise check acran's answer).
The only way I can come up with is:
However there a few problems e.g. if ContainerA crashed ContainerB needs to be recreated as well or you need to copy the file again.
If you wrap it in a Makefile it could look like:
.DEFAULT_GOAL := run
run:
docker-compose up -d containerA
sleep 10
docker cp containerA:/seed-file seed-file
docker-compose up -d containerB
Upvotes: 0
Reputation: 9018
Since docker
defaults to directories as volumes and only bind-mounts a file when the source is an existing file it is a bit harder to use.
With the file
you want to share in your current directory you can use bind-mounts in docker-compose.yml
services:
app1:
# ...
volumes:
- ./file:/path/to/file1:rw
app2:
# ...
volumes:
- ./file:/path/to/file2:rw
This is requires the file to already exist outside the containers. See also the caveats with bind-mounting files in jubnzv's answer.
Depending on your use case maybe a better workaround could be using symlinks and mounting the shared file in a directory volume:
# tree layout in containers:
ContainerA:
|- shared/
| ` shared-file
`- app_folder_a/
|- file-1
|- file-2
|- file-3
`- shared-file-a -> /shared/shared-file
ContainerB:
|- shared/
| ` shared-file
`- app_folder_b/
|- file-a
|- file-b
|- file-c
`- shared-file-b -> /shared/shared-file
# docker-compose.yml
services:
app1:
# ...
volumes:
- ./shared/:/shared/:rw
app2:
# ...
volumes:
- ./shared/:/shared/:rw
Or if you do not want/can have the file or the shared directory on the host you can use named volumes with symlinks:
services:
app1:
# ...
volumes:
- shared:/app_folder_a
app2:
# ...
depends_on:
- app1
volumes:
- shared:/shared
volumes:
shared:
and the shared file symlinked in containerB:
ContainerB:
|- shared/
| ` ...
`- app_folder_b/
|- file-a
|- file-b
|- file-c
`- shared-file-b -> /shared/shared-file-a
The important part here is that when creating the new volume shared
the first time docker
will prepopulate it with the contents of the target directory in the container. So to work correctly app1
need to be started first so the shared
volume is populated with the contents of app_folder_a
- therefore the depends_on
.
With this you then have the shared
volume, populated with the contents of containerA's /app_folder_a/
and mounted to the same as well as on containerB's /shared/
while /app_folder_b/shared-file-b
is a symlink to /shared/shared-file-a
.
Upvotes: 4
Reputation: 1584
You can use volumes to share individual files, rather than directories. But in some cases, you can't write correctly to the mounted files.
Here is a minimal example:
echo 'Test.' > /tmp/1.txt
docker run -it --user $(id -u):$(id -g) --rm -v /tmp/1.txt:/tmp/2.txt:rw alpine
Inside the container you can access /tmp/1.txt
from the host system using in the /tmp/2.txt
path:
/ $ cat /tmp/2.txt
Test.
/ $ echo '123' > /tmp/2.txt
/ $ cat /tmp/2.txt
123
But some utilities will try to create a new inode when writing to the file. For example:
/ $ cp etc/sysctl.conf /tmp/2.txt
cp: can't create '/tmp/2.txt': File exists
The point is that mounting a file as a volume mounts a specific inode inside the container. Some tools that modify files replace the inode with a new one. But you can't do this because you mount a specific inode that points to your file.
Thus, you will need to mount a directory containing the inodes that you can modify inside the container. For more information, see the docker volumes documentation.
Upvotes: 0