docker cp之后的文件所有权 [英] File ownership after docker cp
问题描述
如何控制哪个用户拥有我复制到容器中和从容器中复制的文件?
How can I control which user owns the files I copy in and out of a container?
docker cp
命令关于文件所有权的说法:
The docker cp
command says this about file ownership:
cp
命令的行为类似于Unixcp -a
命令,因为目录被递归复制,并在可能的情况下保留了权限.所有权设置为目的地的用户和主要组.例如,使用根用户的UID:GID
创建复制到容器的文件.复制到本地计算机上的文件是使用调用docker cp
命令的用户的UID:GID
创建的.但是,如果指定-a
选项,则docker cp
会将所有权设置为源用户和主要组.
The
cp
command behaves like the Unixcp -a
command in that directories are copied recursively with permissions preserved if possible. Ownership is set to the user and primary group at the destination. For example, files copied to a container are created withUID:GID
of the root user. Files copied to the local machine are created with theUID:GID
of the user which invoked thedocker cp
command. However, if you specify the-a
option,docker cp
sets the ownership to the user and primary group at the source.
它说复制到容器的文件是作为root用户创建的,但这不是我所看到的.我创建了两个文件,分别由用户ID 1005和1006拥有.这些所有者被转换为容器的用户名称空间.将文件复制到容器中时, -a
选项似乎没有什么区别.
It says that files copied to a container are created as the root user, but that's not what I see. I create two files owned by user id 1005 and 1006. Those owners are translated into the container's user namespace. The -a
option seems to make no difference when I copy the file into a container.
$ 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
选项似乎什么也没做.
When I copy files out of the container, they are always owned by me. Again, the -a
option seems to do nothing.
$ 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
$
推荐答案
In order to get complete control of file ownership, I used the tar stream feature of docker cp
:
如果为
SRC_PATH
或DEST_PATH
指定了-
,则还可以从STDIN
或STDOUT
.
If
-
is specified for either theSRC_PATH
orDEST_PATH
, you can also stream a tar archive fromSTDIN
or toSTDOUT
.
我启动 docker cp
进程,然后向或从该进程流传输tar文件.随着tar条目的通过,我可以随意调整所有权和权限.
I launch the docker cp
process, then stream a tar file to or from the process. As the tar entries go past, I can adjust the ownership and permissions however I like.
这是Python中的一个简单示例,该示例将 sandbox1
容器中/outputs
中的所有文件复制到当前目录,不包括当前目录,因此其权限不进行更改,并强制所有文件对用户具有读/写权限.
Here's a simple example in Python that copies all the files from /outputs
in the sandbox1
container to the current directory, excludes the current directory so its permissions don't get changed, and forces all the files to have read/write permissions for the user.
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()
这篇关于docker cp之后的文件所有权的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!