我正在考虑使用Docker在持续集成(CI)服务器上构建依赖关系,这样我就不必在代理本身上安装所有运行时和库。

为了实现这一点,我需要将容器内部构建的构建工件复制回主机。这可能吗?


当前回答

装载一个“卷”并将工件复制到其中:

mkdir artifacts
docker run -i -v ${PWD}/artifacts:/artifacts ubuntu:14.04 sh << COMMANDS
# ... build software here ...
cp <artifact> /artifacts
# ... copy more artifacts into `/artifacts` ...
COMMANDS

然后,当构建完成并且容器不再运行时,它已经将构建中的工件复制到主机上的工件目录中。

Edit

注意:当您这样做时,可能会遇到docker用户的用户id与当前运行用户的用户id匹配的问题。也就是说,/fartifacts中的文件将显示为用户所有,用户的UID在docker容器中使用。解决此问题的一种方法可能是使用主叫用户的UID:

docker run -i -v ${PWD}:/working_dir -w /working_dir -u $(id -u) \
    ubuntu:14.04 sh << COMMANDS
# Since $(id -u) owns /working_dir, you should be okay running commands here
# and having them work. Then copy stuff into /working_dir/artifacts .
COMMANDS

其他回答

如果您只想从映像(而不是正在运行的容器)中提取文件,可以执行以下操作:

docker运行--rm<image>cat<source>><local_dest>

这将打开容器,写入新文件,然后删除容器。然而,一个缺点是文件权限和修改日期不会被保留。

您不需要使用docker run。

你可以用docker create来完成。

从文档中:

docker create命令在指定的映像上创建一个可写容器层,并为运行指定的命令做好准备。然后将容器ID打印到STDOUT。这与docker run-d类似,只是容器从未启动。

因此,您可以做到:

docker create --name dummy IMAGE_NAME
docker cp dummy:/path/to/file /dest/to/file
docker rm -f dummy

在这里,您永远不会启动容器。这看起来对我有利。

docker cp containerId:source_path destination_path

containerId可以从docker ps-a命令获得

源路径应该是绝对的。例如,如果应用程序/服务目录从docker容器中的应用程序开始,则路径为/app/some_directory/file

示例:docker cp d86844abc129:/app/server/output/server-test.png C:/Users/someone/Desktop/output

装载卷、复制工件、调整所有者id和组id:

mkdir artifacts
docker run -i --rm -v ${PWD}/artifacts:/mnt/artifacts centos:6 /bin/bash << COMMANDS
ls -la > /mnt/artifacts/ls.txt
echo Changing owner from \$(id -u):\$(id -g) to $(id -u):$(id -g)
chown -R $(id -u):$(id -g) /mnt/artifacts
COMMANDS

编辑:请注意,某些命令(如$(id-u))是反斜杠的,因此将在容器中处理,而未反斜杠的命令将在命令发送到容器之前由主机中运行的shell处理。

对于任何试图使用MySQL容器并在您的计算机上本地存储卷的人来说。我使用了这个问题的顶级回复中提供的语法。但必须使用MySQL特有的特定路径

docker cp imageIdHere:/var/lib/mysql pathToYourLocalMachineHere