Docker in Docker cannot mount volume
我奔跑在詹金斯在丛集性在主人和奴隶,都是运行在泊坞窗的容器中。 P / < >
"主机也latest boot2docker VM运行在macos。 P / < >
到允许詹金斯到能到执行部署使用泊坞窗,我docker.sock骑警的码头工人和客户端从主机到詹金斯集装箱像这样: P / < >
1 | docker run -v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/usr/bin/docker -v $HOST_JENKINS_DATA_DIRECTORY/jenkins_data:/var/jenkins_home -v $HOST_SSH_KEYS_DIRECTORY/.ssh/:/var/jenkins_home/.ssh/ -p 8080:8080 jenkins |
我面临的问题,而mounting容的泊坞窗到容器中,是跑在詹金斯的集装箱。例如,如果我需要运行另一个集装箱的集装箱在詹金斯),做以下: P / < >
1 | sudo docker run -v $JENKINS_CONTAINER/deploy.json:/root/deploy.json $CONTAINER_REPO/$CONTAINER_IMAGE |
"runs以上的集装箱,但文件"deploy.json"不是个骑警的文件,但而不是年代的"目录"。即使我在山上的目录级的容,我unable到视图的"文件在resulting集装箱。 P / < >
这是一个问题,因为文件permissions由于码头工人在泊坞窗吗? P / < >
任何pointers会useful! P / < >
谢谢! P / < >
Docker容器中的Docker容器使用父主机的Docker守护进程,因此,安装在"Docker in Docker"案例中的任何卷仍然从主机引用,而不是从容器引用。
因此,从Jenkins容器装载的实际路径在主机中"不存在"。因此,在"docker in docker"容器中创建了一个空目录。当一个目录被装载到一个容器中的一个新的Docker容器上时,同样的事情也适用。
很基本很明显的事情我错过了,但我一打出来就意识到了。
关于与Jenkins相关的用例,您可以通过在主机上创建一个符号链接来简单地伪造路径:
1 | ln -s $HOST_JENKINS_DATA_DIRECTORY/jenkins_data /var/jenkins_home |
另一种方法是使用命名卷或数据卷容器。这样,里面的容器就不需要知道任何关于主机的信息,詹金斯容器和构建容器都以同样的方式引用数据量。
我试过做一些类似于你所做的事情,除了一个代理,而不是使用詹金斯大师。问题是相同的,因为我无法将Jenkins工作区安装在内部容器中。对我有用的是使用数据卷容器方法,代理容器和内部容器都可以看到工作区文件。我喜欢的方法是两个容器以相同的方式引用数据量。用一个内部容器装载目录是很困难的,因为内部容器现在需要知道一些关于其父容器正在运行的主机的信息。
我在这里有关于我的方法的详细博客文章:
http://damhandy.com/2016/03/06/creating-containerized-build-environments-with-the-jenkins-pipeline-plugin-and-docker-well-most-/
以及这里的代码:
https://github.com/damhandy/jenkins-pipeline-docker网站
在我的具体案例中,并不是所有的事情都按照我希望的方式运行在Jenkins管道插件方面。但它确实解决了内部容器能够访问Jenkins工作区目录的问题。
这也可以通过
创建主机端目录并设置允许Docker容器访问的权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | version: '3.1' services: jenkins: build: . image: jenkins ports: - 8080:8080 - 50000:50000 volumes: - /var/run/docker.sock:/var/run/docker.sock - workspace:/var/jenkins_home/workspace/ # Can also do builds/jobs/etc here and below jenkins-lts: build: context: . args: versiontag: lts image: jenkins:lts ports: - 8081:8080 - 50001:50000 volumes: workspace: driver: local driver_opts: type: none o: bind device: /var/jenkins_home/workspace/ |
当您
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ARG versiontag=latest FROM jenkins/jenkins:${versiontag} ENV JAVA_OPTS="-Djenkins.install.runSetupWizard=false" COPY jenkins_config/config.xml /usr/share/jenkins/ref/config.xml.override COPY plugins.txt /usr/share/jenkins/ref/plugins.txt RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt USER root RUN curl -L http://get.docker.io | bash && \ usermod -aG docker jenkins # Since the above takes a while make any other root changes below this line # eg `RUN apt update && apt install -y curl` # drop back to the regular jenkins user - good practice USER jenkins EXPOSE 8080 |
如果你和我一样,不想和詹金斯的安排搞混,也不想太懒惰,不想经历这些麻烦,这里有一个简单的解决方法,我做了这个为我工作。
步骤1-将以下变量添加到管道的环境部分
1 2 3 4 | environment { ABSOLUTE_WORKSPACE ="/home/ubuntu/volumes/jenkins-data/workspace" JOB_WORKSPACE ="\${PWD##*/}" } |
步骤2-使用以下命令运行容器jenkins pipeline,如下所示。
1 2 3 | steps { sh"docker run -v ${ABSOLUTE_WORKSPACE}/${JOB_WORKSPACE}/my/dir/to/mount:/targetPath imageName:tag" } |
Take note of the double quotes in the above statement, Jenkins will not convert the env variables if the quotes are not formatted properly or single quotes are added instead.
每个变量意味着什么?
绝对工作区是我们在启动Jenkins Docker容器时安装的Jenkins卷的路径。在我的例子中,docker run命令如下。
sudo docker run \
-p 80:8080 \
-v /home/ubuntu/volumes/jenkins-data:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
-d -t jenkinsci/blueocean
Thus the varible ABSOLUTE_WORKSPACE=/home/ubuntu/volumes/jenkins-data + /workspace
- job_workspace命令为我们提供代码所在的当前工作区目录。这也是代码库的根目录。只是按照这个答案做参考。
这是怎么工作的?
正如@zephyrplusplus(credits when due)答案中提到的,我们在Jenkins管道中运行的Docker容器的源路径不是当前容器中的路径,而是主机路径。我们在这里所做的就是建造一条通往詹金斯管道的道路。把它装到我们的集装箱里。哇!!
这里有一个小例子来帮助澄清…
解决这个问题的一种方法是使用与目的地完全相同的路径挂载一个目录(在挂载Docker套接字的Docker容器中)。然后,当您从该容器中运行容器时,可以使用
举个例子:
1 2 3 4 5 | # Spin up your container from which you will use docker docker run -v /some/dir:/some/dir -v /var/run/docker.sock:/var/run.docker.sock docker:latest # Now spin up a container from within this container docker run -v /some/dir:/usr/src/app $CONTAINER_IMAGE |
文件夹
这有点类似于在主机上创建符号链接的建议,但我发现这(至少在我的情况下)是一个更干净的解决方案。只是别忘了事后清理主机上的dir!;)