Docker 中的 Docker - 卷不工作:第一级容器中的文件已满,第二层为空 [英] Docker in Docker - volumes not working: Full of files in 1st level container, empty in 2nd tier
问题描述
我在 Docker 中运行 Docker(特别是运行 Jenkins,然后运行 Docker 构建器容器来构建项目映像,然后运行这些容器,然后运行测试容器).
I am running Docker in Docker (specifically to run Jenkins which then runs Docker builder containers to build a project images and then runs these and then the test containers).
jenkins 镜像是这样构建和启动的:
This is how the jenkins image is built and started:
docker build --tag bb/ci-jenkins .
mkdir $PWD/volumes/
docker run -d --network=host
-v /var/run/docker.sock:/var/run/docker.sock
-v /usr/bin/docker:/usr/bin/docker
-v $PWD/volumes/jenkins_home:/var/jenkins_home
--name ci-jenkins bb/ci-jenkins
詹金斯工作正常.但是有一个基于 Jenkinsfile
的作业,它运行这个:
Jenkins works fine. But then there is a Jenkinsfile
based job, which runs this:
docker run -i --rm -v /var/jenkins_home/workspace/forkMV_jenkins-VOLTRON-3057-KQXKVJNXOU4DGSUG3P27IR3QEDHJ6K7HPDEZYN7W6HCOTCH3QO3Q:/tmp/build collab/collab-services-api-mvn-builder:2a074614 mvn -B -T 2C install
这会导致错误:
您指定的目标需要执行项目,但此目录 (/tmp/build) 中没有 POM.
The goal you specified requires a project to execute but there is no POM in this directory (/tmp/build).
当我对容器执行 docker exec -it sh
时,/tmp/build
为空.但是当我在 Jenkins 容器中时,路径 /var/jenkins_home/...QO3Q/
存在,它包含所有已签出并准备好的文件的工作区.
When I do docker exec -it sh
to the container, the /tmp/build
is empty. But when I am in the Jenkins container, the path /var/jenkins_home/...QO3Q/
exists and it contains the workspace with all the files checked out and prepared.
所以我想知道 - Docker 怎样才能愉快地挂载卷然后它是空的?*
更令人困惑的是,此设置适用于我在 Mac 上的同事.我在 Linux、Ubuntu 17.10、Docker 最新版本上.
What's even more confusing, this setup works for my colleague on Mac. I am on Linux, Ubuntu 17.10, Docker latest.
推荐答案
经过一番研究,静下心来思考,才发现Docker-in-Docker并不是真的那么-in-"",因为它是Docker-next-to-Docker".
After some research, calming down and thinking, I realized that Docker-in-Docker is not really so much "-in-", as it is rather "Docker-next-to-Docker".
使容器能够运行另一个容器的技巧是通过卷共享 /var/run/docker.sock
:-v/var/run/docker.sock:/var/run/docker.sock
The trick to make a container able to run another container is sharing /var/run/docker.sock
through a volume: -v /var/run/docker.sock:/var/run/docker.sock
然后容器中的docker
客户端实际调用宿主机上的Docker.
And then the docker
client in the container actually calls Docker on the host.
卷源路径(:
左侧)不是指中间容器,而是指宿主文件系统!
The volume source path (left of :
) does not refer to the middle container, but to the host filesystem!
意识到这一点后,修复方法是使宿主文件系统和 Jenkins(中间)容器中 Jenkins workspace
目录的路径相同:
After realizing that, the fix is to make the paths to the Jenkins workspace
directory the same in the host filesystem and the Jenkins (middle) container:
docker run -d --network=host
...
-v /var/jenkins_home:/var/jenkins_home
瞧!有用.(我创建了一个符号链接而不是移动它,似乎也可以.)
And voilá! It works. (I created a symlink instead of moving it, seems to work too.)
如果您正在查看同事的 Mac,这会有点复杂,因为 Docker 的实现方式有些不同 - 它在基于 Alpine Linux 的 VM 中运行,但假装没有.(不是 100% 确定这一点.)在 Windows 上,我读到路径有另一层抽象 - 从 C:/somewhere/...
映射到类似 Linux 的路径.
It is a bit complicated if you're looking at colleague's Mac, because Docker is implemented a bit differently there - it is running in an Alpine Linux based VM but pretending not to. (Not 100 % sure about that.) On Windows, I read that the paths have another layer of abstraction - mapping from C:/somewhere/...
to a Linux-like path.
我希望我能节省一些时间来弄清楚:)
I hope I'll save someone hours of figuring out :)
这篇关于Docker 中的 Docker - 卷不工作:第一级容器中的文件已满,第二层为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!