Extraire le fichier de l'image docker?

24

Je voudrais extraire un fichier d'une image Docker sans avoir à exécuter l'image.

L' docker saveoption n'est pas actuellement une option viable pour moi car elle enregistre un fichier trop volumineux juste pour annuler le tar d'un fichier spécifique.

BlakBat
la source
Quelle distro utilisez-vous?
ryekayo
@ryekayo: Ubuntu 14, docker 1.12.4 (api 1.24)
BlakBat

Réponses:

21

Vous pouvez extraire des fichiers d'une image avec les commandes suivantes:

docker create $image  # returns container ID
docker cp $container_id:$source_path $destination_path
docker rm $container_id

Selon la docker create documentation , cela n'exécute pas le conteneur:

La docker createcommande crée une couche conteneur inscriptible sur l'image spécifiée et la prépare pour l'exécution de la commande spécifiée. L'ID du conteneur est ensuite imprimé sur STDOUT. Ceci est similaire au fait docker run -dque le conteneur n'est jamais démarré. Vous pouvez ensuite utiliser la docker start <container_id>commande pour démarrer le conteneur à tout moment.


Pour référence (ma réponse précédente), un moyen moins efficace d'extraire un fichier d'une image est le suivant:

docker run some_image cat $file_path > $output_path
bbc
la source
3
Vous voudrez peut-être passer outre le point d'entrée. docker run --entrypoint /bin/sh my_image -c /bin/cat some_file
Andrew
1
Cela exécute l'image, ce qui est précisément ce que je ne voulais pas faire comme indiqué dans ma question.
BlakBat
Ah, c'est un bon point. Je suis d'accord que ma réponse actuelle n'est pas satisfaisante alors.
bbc
1
@BlakBat Cette réponse mise à jour fonctionne-t-elle pour vous? Je suppose que j'aurais dû créer une nouvelle réponse, mais c'est fait maintenant.
bbc
1
@bbc Cette réponse mise à jour ne démarre en fait pas de conteneur (le nœud de la question), et ne nécessite pas d'être root.
BlakBat
2

Rien de ce qui précède n'a fonctionné pour moi. La commande de travail complète est:

docker run --rm --entrypoint /bin/sh image_name -c "cat /path/filename" > output_filename

Sans guillemets catest passé sans nom de fichier, donc il ne sait pas quoi montrer. C'est également une bonne idée de supprimer le conteneur une fois la commande terminée.

sekrett
la source
La commande à laquelle vous faites référence ne fonctionnera qu'en fonction du docker et de la manière dont ENTRYPOINT / CMD a été défini dans le Dockerfile; cela n'a rien à voir avec la citation. Vous dites également de supprimer le conteneur, mais vous spécifiez --rm. Enfin, lorsque j'ai posté ma question, j'ai précisé "sans avoir à lancer l'image" et aucune réponse n'était une solution en tenant compte de cela.
BlakBat
1
Quel que soit le CMD et ENTRYPOINT définis dans Dockerfile, je remplace les deux, donc cela fonctionnerait toujours (sur Linux bien sûr). Qu'entendez-vous par «selon le docker»? Paramètres, version, env, quoi? Votre question n'est pas correcte car les images ne peuvent pas être exécutées, seuls les conteneurs le peuvent. Je pense qu'il n'y a pas de bonne réponse, vous devez gérer de nombreux fichiers ou créer un conteneur temporaire. --rm supprime le conteneur temporaire, les réponses des autres laissent des ordures sur votre disque.
sekrett
1

Si je ne me trompe pas, je pense que les conteneurs Docker stockent les fichiers mis en cache créés dans le répertoire suivant pour Ubuntu:

/var/lib/docker/aufs/diff/<container_id>

De là, vous devriez pouvoir accéder au système de fichiers et récupérer vos fichiers.

ryekayo
la source
Nan. Ce répertoire contient uniquement layersizeet json, et n'est pas non plus lisible par l'utilisateur (même si l'utilisateur est dans le groupe docker). /var/lib/docker/aufs/diffcontiendra le fichier que je recherche (mais n'est pas classé par ID de conteneur) et n'est pas non plus lisible.
BlakBat
Donnez-moi quelques-uns et je vais le chercher. Je sais pertinemment qu'il existe un moyen de récupérer les fichiers sans entrer dans le conteneur ni l'exécuter.
ryekayo
Par non lisible, comment ça se voit? J'ai trouvé un exemple où vous pouvez extraire des fichiers texte des conteneurs en allant dans le répertoire / var / lib / docker / aufs / diff / *
ryekayo
Mon erreur. L'utilisateur peut accéder /var/lib/docker/aufs(mais pas à tous les autres répertoires /var/lib/docker/)
BlakBat
Pouvez-vous accéder en tant que root?
ryekayo
0

Si le stockage de la sortie complète de docker saven'est pas une option, vous pouvez utiliser des pipelines pour en extraire uniquement le fichier nécessaire.

Malheureusement, comme la sortie est un "goudron de goudron", il peut s'agir d'un processus légèrement itératif.

Ce que j'ai fait lorsque j'ai eu besoin d'extraire un fichier tout à l'heure était:

1) Déterminez quelle version de l'image le fichier qui vous intéresse a changé le plus récemment (la façon dont vous procédez dépend probablement de votre image) et la date de sa création / sauvegarde

2) Obtenez la table des matières complète de la sortie de la docker savecommande avec:

docker save IMAGE_NAME | tar -tvf -

3) Affinez le layer.tar(s) fichier (s) dans la sortie de cette commande qui correspondent à la date de l'image que vous avez déterminée à l'étape 1. (vous pouvez ajouter | grep layer.tarpour simplement afficher ces fichiers)

4) Extrayez ce layer.tarfichier en sortie standard et récupérez la table des matières:

docker save IMAGE_NAME | tar -xf - -O CHECKSUM_FROM_LIST/layer.tar | tar -tvf -

5) Vérifiez que le fichier souhaité est répertorié et extrayez-le une fois que vous avez trouvé le nom:

docker save IMAGE_NAME | tar -xf - -O CHECKSUM_FROM_LIST/layer.tar | tar -xf - PATH/TO/YOUR/FILE

Si plusieurs layer.tarfichiers correspondent à la date recherchée à l'étape 2/3, vous devrez peut-être répéter l'étape 4 pour chacun d'eux jusqu'à ce que vous trouviez le bon.

Remplacez le texte en majuscules dans les commandes ci-dessus par les noms d'image, les sommes de contrôle et les noms de fichiers corrects pour votre cas.

Michael Firth
la source