2017-10-06 4 views
0

Comment puis-je contrôler l'utilisateur propriétaire des fichiers copiés dans et hors d'un conteneur?Propriété de fichier après docker cp

Le docker cp command dit ceci au sujet de la propriété du fichier:

Les comme la commande Unix cp -a se comporte de commande cp dans les répertoires que sont copiés récursive avec des autorisations conservées si possible. La propriété est définie sur l'utilisateur et le groupe principal sur la destination. Par exemple, les fichiers copiés dans un conteneur sont créés avec UID:GID de l'utilisateur root. Les fichiers copiés sur la machine locale sont créés avec le UID:GID de l'utilisateur qui a appelé la commande docker cp. Toutefois, si vous spécifiez l'option -a, docker cp définit la propriété pour l'utilisateur et le groupe principal à la source.

Il est dit que les fichiers copiés dans un conteneur sont créés en tant qu'utilisateur root, mais ce n'est pas ce que je vois. Je crée deux fichiers appartenant aux ID utilisateur 1005 et 1006. Ces propriétaires sont traduits dans l'espace de noms d'utilisateur du conteneur. L'option -a semble ne faire aucune différence lorsque je copie le fichier dans un conteneur.

$ 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 

Lorsque je copie des fichiers hors du conteneur, ils sont toujours détenus par moi. Encore une fois, l'option -a semble ne rien faire.

$ 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 
$ 

Répondre

0

Afin d'obtenir le contrôle total de la propriété des fichiers, j'ai utilisé la tar stream caractéristique de docker cp:

Si - est spécifié pour le SRC_PATH ou DEST_PATH, vous pouvez également diffuser une archive tar de STDIN ou STDOUT.

Je lance le processus docker cp, puis envoie un fichier tar vers ou depuis le processus. Comme les entrées tar passent, je peux ajuster la propriété et les permissions comme j'aime.

Voici un exemple simple en Python qui copie tous les fichiers de /outputs dans le conteneur sandbox1 dans le répertoire courant, exclut le répertoire courant si ses autorisations ne sont pas modifiées, et les forces de tous les fichiers d'avoir des autorisations de lecture/écriture pour l'utilisateur.

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