docker cp之后的文件所有权

docker cp之后的文件所有权,docker,file-permissions,Docker,File Permissions,如何控制哪些用户拥有我在容器中复制和复制的文件 有关文件所有权的说明如下: cp命令的行为类似于Unixcp-a命令,在可能的情况下,递归复制目录并保留权限。所有权设置为目标的用户和主组。例如,复制到容器中的文件是使用root用户的UID:GID创建的。复制到本地计算机的文件是使用调用docker cp命令的用户的UID:GID创建的。但是,如果指定-a选项,docker cp将在源位置设置用户和主组的所有权 它说复制到容器中的文件是作为根用户创建的,但这不是我看到的。我创建了两个由用户ID10

如何控制哪些用户拥有我在容器中复制和复制的文件

有关文件所有权的说明如下:

cp
命令的行为类似于Unix
cp-a
命令,在可能的情况下,递归复制目录并保留权限。所有权设置为目标的用户和主组。例如,复制到容器中的文件是使用root用户的
UID:GID
创建的。复制到本地计算机的文件是使用调用
docker cp
命令的用户的
UID:GID
创建的。但是,如果指定
-a
选项,
docker cp
将在源位置设置用户和主组的所有权

它说复制到容器中的文件是作为根用户创建的,但这不是我看到的。我创建了两个由用户ID1005和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
tar -cf - foo.bar --mode u=+r,g=-rwx,o=-rwx --owner root --group root | docker cp - nginx:/
docker exec nginx sh -c 'ls -ahl /foo.bar'
>> -r--------    1 root     root           0 Sep 21 14:45 /foo.bar
当我从容器中复制文件时,它们总是属于我。同样地,
-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的功能:

如果为
SRC_路径
DEST_路径
指定了
-
,则还可以将tar存档从
STDIN
或流到
STDOUT

我启动
docker cp
进程,然后将tar文件流式传输到该进程或从该进程流式传输。随着tar条目的过去,我可以随意调整所有权和权限

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

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()

除了@Don Kirkby的答案之外,让我在bash/shell脚本中提供一个类似的示例,用于在应用与原始文件不同的所有权和权限的情况下将某些内容复制到容器中

让我们从一个小映像创建一个新容器,它将自动运行:

docker run -d --name nginx nginx:alpine
现在,我们将创建一个新文件,该文件由当前用户拥有,并具有默认权限:

touch foo.bar
ls -ahl foo.bar
>> -rw-rw-r-- 1 my-user my-group 0 Sep 21 16:45 foo.bar
docker cp foo.bar nginx:/foo.bar
docker exec nginx sh -c 'ls -ahl /foo.bar'
>> -rw-rw-r--    1 4098     4098           0 Sep 21 14:45 /foo.bar
将此文件复制到容器中会将所有权和组设置为我的用户的
UID
,并保留权限:

touch foo.bar
ls -ahl foo.bar
>> -rw-rw-r-- 1 my-user my-group 0 Sep 21 16:45 foo.bar
docker cp foo.bar nginx:/foo.bar
docker exec nginx sh -c 'ls -ahl /foo.bar'
>> -rw-rw-r--    1 4098     4098           0 Sep 21 14:45 /foo.bar
不过,通过使用一点
tar
解决方案,我可以更改容器内部应用的所有权和权限

$ 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
tar -cf - foo.bar --mode u=+r,g=-rwx,o=-rwx --owner root --group root | docker cp - nginx:/
docker exec nginx sh -c 'ls -ahl /foo.bar'
>> -r--------    1 root     root           0 Sep 21 14:45 /foo.bar
tar
选项说明:

  • c
    创建一个新的归档文件,而不是将其解包
  • f-
    将写入
    stdout
    而不是文件
  • foo.bar
    是要打包的输入文件
  • --mode
    指定目标的权限。与chown类似,它们可以用符号表示法或八进制数表示
  • --owner
    设置文件的新所有者
  • --group
    设置文件的新组
docker cp-
stdin
读取要复制到容器中的文件


当文件需要在启动之前复制到已创建的容器中时,此方法非常有用,例如,
docker exec
不是一个选项(只能在运行的容器上操作)。

您还可以通过以root用户身份登录容器来更改所有权:

docker exec -it --user root <container-id> /bin/bash
chown -R <username>:<groupname> <folder/file>
docker exec-it--用户root/bin/bash
周-R:
只需一行代码(类似于@ramu的答案),使用root进行呼叫:

docker exec -u 0 -it <container-id> chown node:node /home/node/myfile
docker exec-u 0-it chown节点:node/home/node/myfile

我在docker容器中使用非root用户时遇到问题。我已经解决了这个问题,在容器中用'-n'列出了文件,因此是'docker exec nginx sh-c'ls-ahln/foo.bar',并使用tar参数上的数字,因此'tar-cf-foo.bar--mode u=+r,g=-rwx,o=-rwx--owner 1000--group1000 | docker cp-nginx://'