如何在 Docker-in-Docker 容器之间重新共享卷?
How do I re-share volumes between Docker-in-Docker containers?
我已将卷 shared
安装到我的服务 main
。
现在我正在尝试将相同的卷安装到另一个容器 client
,该容器从 main
容器中以 docker-compose up client
开始(Docker-in-Docker ):
version: "3.8"
# set COMPOSE_PROJECT_NAME=default before running `docker-compose up main`
services:
main:
image: rbird/docker-compose:python-3.9-slim-buster
privileged: true
entrypoint: docker-compose up client # start client
volumes:
- //var/run/docker.sock:/var/run/docker.sock
- ./docker-compose.yml:/docker-compose.yml
- ./shared:/shared
client:
image: alpine
entrypoint: sh -c "ls shared*"
profiles:
- do-not-run-directly
volumes:
- /shared:/shared1
- ./shared:/shared2
我得到的输出是:
[+] Running 2/2
- Network test_default Created 0.0s
- Container test_main_1 Started 0.9s
Attaching to main_1
Recreating default_client_1 ... done
Attaching to default_client_1
main_1 | client_1 | shared1:
main_1 | client_1 |
main_1 | client_1 | shared2:
main_1 | default_client_1 exited with code 0
main_1 exited with code 0
所以文件夹 /shared2
和 /shared2
是空的,尽管它们包含主机目录和 main
容器中的文件。
如何在容器之间重新共享卷?
或者有没有办法在所有容器之间共享一个主机目录,即使是那些由其中一个容器启动的?
这里最干净的答案是删除 main:
容器和 client:
容器的 profiles:
块,以及主机上的 运行 docker-compose
直接。
您在此处的设置使用主机的 Docker 套接字。 (它不是“Docker-in-Docker”;该设置通常是 运行 在容器中安装第二个 Docker 守护进程的更令人困惑的情况。)意味着容器内的 Docker Compose 实例向主机的 Docker 守护进程发送指令,告诉它启动哪些容器。您正在将 docker-compose.yml
文件安装在容器的根目录中,因此 ./shared
路径也相对于 /
进行解释。
这意味着 主机的 Docker 守护进程正在接收一个请求,要求在新容器内创建一个容器 /shared
安装在 /shared1
上,还有 /shared
(./shared
,相对于路径 /
)安装在 /shared2
上。 host's Docker 守护程序使用 host 路径创建此容器。如果你查看你的主机系统,你可能会在主机文件系统根目录中看到一个空的 /shared
目录,如果你在那里创建文件,它们将出现在新容器的 /shared1
和 /shared2
中目录。
一般来说,无法将一个容器的文件系统挂载到另一个容器。如果您尝试从容器中 运行 docker
(或 docker-compose
),您必须从外部了解您自己的文件系统中哪些是卷挂载以及究竟挂载了什么。
如果可以,请避免容器启动其他容器和容器之间共享卷的方法。如果有可能启动另一个容器,并且该另一个容器可以挂载主机文件系统的任意部分,那么您就可以非常简单地 root 整个主机。除了安全问题之外,您在此处注意到的路径复杂性也很难解决。共享卷在非 Docker 环境中效果不佳(例如,在 Kubernetes 中,很难获得 ReadWriteMany 卷,并且容器通常不会彼此位于同一主机上)并且周围存在复杂性权限以及对同一文件有多个读者和作者。
相反,仅在主机上启动 docker
和 docker-compose
命令(作为非开发人员系统上的特权用户)。如果一个容器需要将只读内容单向发布到另一个容器,例如静态资产,请创建一个自定义图像 COPY --from=
一个图像到另一个图像。否则请考虑使用专门构建的网络可访问存储(如数据库),它不特别依赖于文件系统并且知道如何处理并发访问。
我已将卷 shared
安装到我的服务 main
。
现在我正在尝试将相同的卷安装到另一个容器 client
,该容器从 main
容器中以 docker-compose up client
开始(Docker-in-Docker ):
version: "3.8"
# set COMPOSE_PROJECT_NAME=default before running `docker-compose up main`
services:
main:
image: rbird/docker-compose:python-3.9-slim-buster
privileged: true
entrypoint: docker-compose up client # start client
volumes:
- //var/run/docker.sock:/var/run/docker.sock
- ./docker-compose.yml:/docker-compose.yml
- ./shared:/shared
client:
image: alpine
entrypoint: sh -c "ls shared*"
profiles:
- do-not-run-directly
volumes:
- /shared:/shared1
- ./shared:/shared2
我得到的输出是:
[+] Running 2/2
- Network test_default Created 0.0s
- Container test_main_1 Started 0.9s
Attaching to main_1
Recreating default_client_1 ... done
Attaching to default_client_1
main_1 | client_1 | shared1:
main_1 | client_1 |
main_1 | client_1 | shared2:
main_1 | default_client_1 exited with code 0
main_1 exited with code 0
所以文件夹 /shared2
和 /shared2
是空的,尽管它们包含主机目录和 main
容器中的文件。
如何在容器之间重新共享卷?
或者有没有办法在所有容器之间共享一个主机目录,即使是那些由其中一个容器启动的?
这里最干净的答案是删除 main:
容器和 client:
容器的 profiles:
块,以及主机上的 运行 docker-compose
直接。
您在此处的设置使用主机的 Docker 套接字。 (它不是“Docker-in-Docker”;该设置通常是 运行 在容器中安装第二个 Docker 守护进程的更令人困惑的情况。)意味着容器内的 Docker Compose 实例向主机的 Docker 守护进程发送指令,告诉它启动哪些容器。您正在将 docker-compose.yml
文件安装在容器的根目录中,因此 ./shared
路径也相对于 /
进行解释。
这意味着 主机的 Docker 守护进程正在接收一个请求,要求在新容器内创建一个容器 /shared
安装在 /shared1
上,还有 /shared
(./shared
,相对于路径 /
)安装在 /shared2
上。 host's Docker 守护程序使用 host 路径创建此容器。如果你查看你的主机系统,你可能会在主机文件系统根目录中看到一个空的 /shared
目录,如果你在那里创建文件,它们将出现在新容器的 /shared1
和 /shared2
中目录。
一般来说,无法将一个容器的文件系统挂载到另一个容器。如果您尝试从容器中 运行 docker
(或 docker-compose
),您必须从外部了解您自己的文件系统中哪些是卷挂载以及究竟挂载了什么。
如果可以,请避免容器启动其他容器和容器之间共享卷的方法。如果有可能启动另一个容器,并且该另一个容器可以挂载主机文件系统的任意部分,那么您就可以非常简单地 root 整个主机。除了安全问题之外,您在此处注意到的路径复杂性也很难解决。共享卷在非 Docker 环境中效果不佳(例如,在 Kubernetes 中,很难获得 ReadWriteMany 卷,并且容器通常不会彼此位于同一主机上)并且周围存在复杂性权限以及对同一文件有多个读者和作者。
相反,仅在主机上启动 docker
和 docker-compose
命令(作为非开发人员系统上的特权用户)。如果一个容器需要将只读内容单向发布到另一个容器,例如静态资产,请创建一个自定义图像 COPY --from=
一个图像到另一个图像。否则请考虑使用专门构建的网络可访问存储(如数据库),它不特别依赖于文件系统并且知道如何处理并发访问。