docker cp后的文件所有权

我如何控制哪个用户拥有我从容器中复制的文件?

docker cp命令对文件所有权进行了说明:

cp命令的行为与Unix cp -a命令的行为相同,即在可能的情况下保留权限,recursion复制该目录。 所有权设置为目标用户和主要组。 例如,复制到容器的文件是使用根用户的UID:GID创build的。 复制到本地机器的文件是使用调用docker cp命令的用户的UID:GID创build的。 但是,如果指定-a选项,则docker cp将所有权设置为源用户和主组。

它说复制到容器的文件是以root用户身份创build的,但这不是我所看到的。 我创build了由用户ID 1005和1006拥有的两个文件。这些所有者被翻译成容器的用户名称空间。 当我将文件复制到容器中时, -a选项似乎没有什么区别。

 $ sudo chown 1005:1005 test.txt $ ls -l test.txt -rw-r--r-- 1 1005 1005 29 Oct 6 12:43 test.txt $ docker volume create sandbox1 sandbox1 $ docker run --name run1 -vsandbox1:/data alpine echo OK OK $ docker cp test.txt run1:/data/test1005.txt $ docker cp -a test.txt run1:/data/test1005a.txt $ sudo chown 1006:1006 test.txt $ docker cp test.txt run1:/data/test1006.txt $ docker cp -a test.txt run1:/data/test1006a.txt $ docker run --rm -vsandbox1:/data alpine ls -l /data total 16 -rw-r--r-- 1 1005 1005 29 Oct 6 19:43 test1005.txt -rw-r--r-- 1 1005 1005 29 Oct 6 19:43 test1005a.txt -rw-r--r-- 1 1006 1006 29 Oct 6 19:43 test1006.txt -rw-r--r-- 1 1006 1006 29 Oct 6 19:43 test1006a.txt 

当我从容器中复制文件时,它们总是由我拥有。 再次, -a选项似乎什么都不做。

 $ docker run --rm -vsandbox1:/data alpine cp /data/test1006.txt /data/test1007.txt $ docker run --rm -vsandbox1:/data alpine chown 1007:1007 /data/test1007.txt $ docker cp run1:/data/test1006.txt . $ docker cp run1:/data/test1007.txt . $ docker cp -a run1:/data/test1006.txt test1006a.txt $ docker cp -a run1:/data/test1007.txt test1007a.txt $ ls -l test*.txt -rw-r--r-- 1 don don 29 Oct 6 12:43 test1006a.txt -rw-r--r-- 1 don don 29 Oct 6 12:43 test1006.txt -rw-r--r-- 1 don don 29 Oct 6 12:47 test1007a.txt -rw-r--r-- 1 don don 29 Oct 6 12:47 test1007.txt -rw-r--r-- 1 1006 1006 29 Oct 6 12:43 test.txt $ 

为了完全控制文件所有权,我使用了docker cp的tarstream特性:

如果为SRC_PATHDEST_PATH指定了-也可以从STDINSTDOUTstream式传输tar归档文件。

我启动docker cp进程,然后将tar文件docker cp进程。 随着tar条目的过去,我可以调整所有权和权限,但是我喜欢。

以下是Python中的一个简单示例, sandbox1容器中的所有文件/outputs sandbox1到当前目录,排除当前目录,使其权限不被更改,并强制所有文件对用户具有读/写权限。

 from subprocess import Popen, PIPE, CalledProcessError import tarfile def main(): export_args = ['sudo', 'docker', 'cp', 'sandbox1:/outputs/.', '-'] exporter = Popen(export_args, stdout=PIPE) tar_file = tarfile.open(fileobj=exporter.stdout, mode='r|') tar_file.extractall('.', members=exclude_root(tar_file)) exporter.wait() if exporter.returncode: raise CalledProcessError(exporter.returncode, export_args) def exclude_root(tarinfos): print('\nOutputs:') for tarinfo in tarinfos: if tarinfo.name != '.': assert tarinfo.name.startswith('./'), tarinfo.name print(tarinfo.name[2:]) tarinfo.mode |= 0o600 yield tarinfo main()