我想在 docker 容器之间共享单个文件
ContainerA:
- file-1
- file-2
- file-3
- shared-file
ContainerB
- file-a
- file-b
- file-c
- shared-file
无法为我共享完整的卷。 容器中的路径不一样。
答案 0 :(得分:2)
由于 docker
默认将目录作为卷,并且仅当源是现有文件时才绑定挂载文件,因此使用起来有点困难。
如果您想在当前目录中共享 file
,您可以在 docker-compose.yml
中使用绑定挂载
services:
app1:
# ...
volumes:
- ./file:/path/to/file1:rw
app2:
# ...
volumes:
- ./file:/path/to/file2:rw
这要求文件已经存在于容器之外。另请参阅 jubnzv's answer 中绑定挂载文件的注意事项。
根据您的用例,可能更好的解决方法是使用 symlinks 并将共享文件安装在目录卷中:
# 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
或者,如果您不想/不能在主机上拥有文件或共享目录,您可以使用带符号链接的命名卷:
services:
app1:
# ...
volumes:
- shared:/app_folder_a
app2:
# ...
depends_on:
- app1
volumes:
- shared:/shared
volumes:
shared:
和容器B中符号链接的共享文件:
ContainerB:
|- shared/
| ` ...
`- app_folder_b/
|- file-a
|- file-b
|- file-c
`- shared-file-b -> /shared/shared-file-a
这里的重要部分是,当第一次创建新卷 shared
时,docker
将使用容器中目标目录的内容预先填充它。因此,要正常工作,需要先启动 app1
,以便 shared
卷填充 app_folder_a
的内容 - 因此 depends_on
。
这样你就拥有了 shared
卷,其中填充了 containerA 的 /app_folder_a/
的内容,并安装到了同一个以及 containerB 的 /shared/
上,而 /app_folder_b/shared-file-b
是一个/shared/shared-file-a
的符号链接。
答案 1 :(得分:0)
您可以使用卷来共享单个文件,而不是目录。但在某些情况下,您无法正确写入已挂载的文件。
这是一个最小的例子:
Enter birth date in the format: hh:min/dd.mm.yyyy
13:28/04.03.2021
NOW: 1614853702 BD: 1614853680
seconds elapsed: 22
year 70
mon 0
mday 1
hour 0
min 0
sec 22
在容器内,您可以使用 echo 'Test.' > /tmp/1.txt
docker run -it --user $(id -u):$(id -g) --rm -v /tmp/1.txt:/tmp/2.txt:rw alpine
路径从主机系统访问 /tmp/1.txt
:
/tmp/2.txt
但是一些实用程序会在写入文件时尝试创建一个新的 inode。例如:
/ $ cat /tmp/2.txt
Test.
/ $ echo '123' > /tmp/2.txt
/ $ cat /tmp/2.txt
123
重点是将文件安装为卷会在容器内安装特定的 inode。一些修改文件的工具会用新的 inode 替换 inode。但是您不能这样做,因为您挂载了一个指向您的文件的特定 inode。
因此,您需要挂载一个包含可以在容器内修改的 inode 的目录。有关详细信息,请参阅 docker volumes documentation。
答案 2 :(得分:0)
如果 containerA 在某个路径创建一个文件并覆盖符号链接,我认为不可能用“干净”的方法来做到这一点(否则检查 acran 的答案)。
我能想到的唯一方法是:
但是有一些问题,例如如果 ContainerA 崩溃了 ContainerB 也需要重新创建,或者您需要再次复制文件。
如果您将其包装在 Makefile 中,它可能如下所示:
.DEFAULT_GOAL := run
run:
docker-compose up -d containerA
sleep 10
docker cp containerA:/seed-file seed-file
docker-compose up -d containerB