web-dev-qa-db-fra.com

Docker - Comment puis-je copier un fichier d'une image sur un hôte?

Ma question concerne cette question sur la copie de fichiers de conteneurs à des hôtes; J'ai un fichier Docker qui récupère les dépendances, compile un artefact de construction à partir de la source et exécute un exécutable. Je souhaite également copier l'artefact de construction (dans mon cas, il s'agit d'un .Zip produit par sbt dist dans '../ target/`, mais je pense que cette question s'applique également aux fichiers jar, binaires, etc. 

docker cp fonctionne sur des conteneurs, pas des images; Ai-je besoin de démarrer un conteneur simplement pour en extraire un fichier? Dans un script, j'ai essayé d'exécuter /bin/bash en mode interactif en arrière-plan, de copier le fichier, puis de tuer le conteneur, mais cela semble correct. Y a-t-il un meilleur moyen?

D'autre part, je voudrais éviter de décompresser un fichier .tar après avoir exécuté docker save $IMAGENAME uniquement pour extraire un fichier (mais cela semble être l'option la plus simple, si elle est la plus lente, actuellement). 

J'utiliserais des volumes de docker, par exemple:

docker run -v hostdir:out $IMAGENAME /bin/cp/../blah.Zip /out

mais j’exécute boot2docker sous OSX et je ne sais pas comment écrire directement sur mon système de fichiers hôte Mac (des volumes en lecture-écriture montent dans ma machine virtuelle boot2docker, ce qui signifie que je ne peux pas partager facilement un script pour extraire blah.Zip image avec les autres.

48
Mark

Répondre à une vieille question pour des références. Pour copier un fichier à partir d'une image, créez un conteneur temporaire, copiez-le puis supprimez-le:

id=$(docker create image-name)
docker cp $id:path - > local-tar-file
docker rm -v $id
89
Igor Bukanov

Malheureusement, il ne semble pas y avoir de moyen de copier des fichiers directement à partir d'images Docker. Vous devez d'abord créer un conteneur, puis copier le fichier à partir du conteneur.

Cependant, si votre image contient une commande cat (et cela se fera souvent), vous pouvez le faire avec une seule commande:

docker run --rm --entrypoint cat yourimage  /path/to/file > path/to/destination

Si votre image ne contient pas cat, créez simplement un conteneur et utilisez la commande docker cp comme suggéré dans la réponse d'Igor.

31
fons

Une option beaucoup plus rapide consiste à copier le fichier du conteneur en cours d'exécution sur un volume monté:

time docker run -v $PWD:/opt/mount --rm --entrypoint cp image:version /data/libraries.tgz /opt/mount/libraries.tgz

real 0m0.446s

CONTRE 

docker run --rm --entrypoint cat image:version /data/libraries.tgz > libraries.tgz

real 0m9.014s

8
Mikko

Le commentaire du parent a déjà montré comment utiliser cat . Vous pouvez aussi utiliser tar de la même manière:

docker run yourimage tar -c -C /my/directory subfolder | tar x
8
wedesoft

J'utilise boot2docker sur MacOS. Je peux vous assurer que les scripts basés sur "docker cp" sont portables. Parce que toute commande est relayée à l'intérieur de boot2docker mais que le flux binaire est retransmis au client en ligne de commande de docker exécuté sur votre mac. Les opérations d'écriture à partir du client docker sont donc exécutées à l'intérieur du serveur et écrites dans l'instance du client en cours d'exécution!

Je partage un script de sauvegarde des volumes de menu fixe avec tous les conteneurs de menu fixe que je fournis et mes scripts de sauvegarde sont testés sous Linux et MacOS avec boot2docker. Les sauvegardes peuvent être facilement échangées entre les plates-formes. Fondamentalement, j'exécute la commande suivante dans mon script:

docker run --name=bckp_for_volume --rm --volumes-from jenkins_jenkins_1 -v /Users/github/jenkins/backups:/backup busybox tar cf /backup/JenkinsBackup-2015-07-09-14-26-15.tar /jenkins

Exécute un nouveau conteneur busybox et monte le volume de mon conteneur jenkins avec le nom jenkins_jenkins_1. Le volume entier est écrit dans les sauvegardes de fichier/JenkinsBackup-2015-07-09-14-26-15.tar

J'ai déjà déplacé des archives entre le conteneur linux et mon conteneur mac sans aucun ajustement du script de sauvegarde ou de restauration. Si c'est ce que vous voulez, vous trouverez le script entier dans un tutoriel ici: blacklabelops/jenkins

0
blacklabelops

Vous pourriez lier un chemin local de l'hôte vers un chemin du conteneur, puis cp le (s) fichier (s) souhaité (s) vers ce chemin à la fin de votre script.

$ docker run -d \
  -it \
  --name devtest \
  --mount type=bind,source="$(pwd)"/target,target=/app \
  nginx:latest

Ensuite, il n'est pas nécessaire de copier après.

0
ryanjdillon