Copie de fichiers du conteneur Docker vers l’hôte

Je pense utiliser Docker pour construire mes dépendances sur un serveur à continuous integration (CI), de manière à ne pas avoir à installer tous les runtimes et bibliothèques sur les agents eux-mêmes. Pour ce faire, je devrais copier les artefacts de build construits à l’intérieur du conteneur dans l’hôte.

Est-ce possible?

Pour copier un fichier depuis un conteneur vers l’hôte, vous pouvez utiliser la commande

docker cp :/file/path/within/container /host/path/target 

Voici un exemple:

 [jalal@goku scratch]$ sudo docker cp goofy_roentgen:/out_read.jpg . 

Goofy_roentgen est le nom que j’ai de la commande suivante:

 [jalal@goku scratch]$ sudo docker ps [sudo] password for jalal: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1b4ad9311e93 bamos/openface "/bin/bash" 33 minutes ago Up 33 minutes 0.0.0.0:8000->8000/tcp, 0.0.0.0:9000->9000/tcp goofy_roentgen 

Montez un “volume” et copiez-y les artefacts:

 mkdir artifacts docker run -i -v ${PWD}/artifacts:/artifacts ubuntu:14.04 sh << COMMANDS # ... build software here ... cp  /artifacts # ... copy more artifacts into `/artifacts` ... COMMANDS 

Ensuite, lorsque la génération se termine et que le conteneur n’est plus en cours d’exécution, il a déjà copié les artefacts de la génération dans le répertoire des artifacts sur l’hôte.

MODIFIER:

CAVEAT: Lorsque vous faites cela, vous pouvez rencontrer des problèmes avec l’ID utilisateur de l’utilisateur du docker correspondant à l’ID utilisateur en cours d’exécution. Autrement dit, les fichiers dans /artifacts seront affichés comme appartenant à l’utilisateur avec l’UID de l’utilisateur utilisé dans le conteneur docker. Un moyen de contourner cela peut être d’utiliser l’UID de l’utilisateur appelant:

 docker run -i -v ${PWD}:/working_dir -w /working_dir -u $(id -u) \ ubuntu:14.04 sh << COMMANDS # Since $(id -u) owns /working_dir, you should be okay running commands here # and having them work. Then copy stuff into /working_dir/artifacts . COMMANDS 

Montez un volume, copiez les artefacts, ajustez l’ID du propriétaire et l’ID du groupe:

 mkdir artifacts docker run -i --rm -v ${PWD}/artifacts:/mnt/artifacts centos:6 /bin/bash << COMMANDS ls -la > /mnt/artifacts/ls.txt echo Changing owner from \$(id -u):\$(id -g) to $(id -u):$(id -u) chown -R $(id -u):$(id -u) /mnt/artifacts COMMANDS 

tldr;

 $ docker run --rm -iv${PWD}:/host-volume my-image sh -s < 

Plus long...

docker run avec un volume hôte, chown l'artefact, cp l'artefact au volume hôte:

 $ docker build -t my-image - < FROM busybox > WORKDIR /workdir > RUN touch foo.txt bar.txt qux.txt > EOF Sending build context to Docker daemon 2.048kB Step 1/3 : FROM busybox ---> 00f017a8c2a6 Step 2/3 : WORKDIR /workdir ---> Using cache ---> 36151d97f2c9 Step 3/3 : RUN touch foo.txt bar.txt qux.txt ---> Running in a657ed4f5cab ---> 4dd197569e44 Removing intermediate container a657ed4f5cab Successfully built 4dd197569e44 $ docker run --rm -iv${PWD}:/host-volume my-image sh -s < '/host-volume/bar.txt' 'foo.txt' -> '/host-volume/foo.txt' 'qux.txt' -> '/host-volume/qux.txt' $ ls -n total 0 -rw-r--r-- 1 10335 11111 0 May 7 18:22 bar.txt -rw-r--r-- 1 10335 11111 0 May 7 18:22 foo.txt -rw-r--r-- 1 10335 11111 0 May 7 18:22 qux.txt 

Cette astuce fonctionne parce que l'invocation de chown dans l' hérédité prend les valeurs $(id -u):$(id -g) de l'extérieur du conteneur en cours d'exécution; c'est-à-dire l'hôte du docker.

Les avantages par rapport à docker cp sont les suivants:

  • vous n'avez pas à docker run --name votre conteneur avant
  • vous n'avez pas à docker container rm après

Si vous n’avez pas de conteneur en cours d’exécution, juste une image, et en supposant que vous souhaitiez copier uniquement un fichier texte, vous pouvez faire quelque chose comme ceci:

 docker run the-image cat path/to/container/file.txt > path/to/host/file.txt 

Je poste ceci pour toute personne qui utilise Docker pour Mac. C’est ce qui a fonctionné pour moi:

  $ mkdir mybackup # local directory on Mac $ docker run --rm --volumes-from  \ -v `pwd`/mybackup:/backup \ busybox \ cp /data/mydata.txt /backup 

Notez que lorsque je monte en utilisant -v ce répertoire de backup est automatiquement créé.

J’espère que cela sera utile à quelqu’un un jour. 🙂

Vous n’avez pas besoin d’utiliser docker run

Vous pouvez le faire avec docker create

À partir de la documentation La commande docker create crée un calque de conteneur accessible en écriture sur l’image spécifiée et le prépare pour l’exécution de la commande spécifiée. L’ID du conteneur est ensuite imprimé sur STDOUT. Ceci est similaire à docker run -d sauf que le conteneur n’est jamais démarré.

Donc, vous pouvez faire

 docker create -ti --name dummy IMAGE_NAME bash docker cp dummy:/path/to/file /dest/to/file docker rm -fv dummy 

Ici, vous ne démarrez jamais le conteneur. Cela m’a semblé bénéfique.

La plupart des réponses n’indiquent pas que le conteneur doit s’exécuter avant que docker cp ne fonctionne:

 docker build -t IMAGE_TAG . docker run -d IMAGE_TAG CONTAINER_ID=$(docker ps -alq) # If you do not know the exact file name, you'll need to run "ls" # FILE=$(docker exec CONTAINER_ID sh -c "ls /path/*.zip") docker cp $CONTAINER_ID:/path/to/file . docker stop $CONTAINER_ID 

En tant que solution plus générale, il existe un plug-in CloudBees pour Jenkins à créer dans un conteneur Docker . Vous pouvez sélectionner une image à utiliser à partir d’un registre Docker ou définir un fichier Dockerfile à générer et à utiliser.

Il montera l’espace de travail dans le conteneur en tant que volume (avec l’utilisateur approprié), le définira comme votre répertoire de travail, exécutera toutes les commandes que vous demandez (dans le conteneur). Vous pouvez également utiliser le plug-in docker-workflow (si vous préférez le code sur l’interface utilisateur) pour cela, avec la commande image.inside () {}.

Fondamentalement, tout cela, cuit dans votre serveur CI / CD, puis certains.

Si vous voulez simplement extraire un fichier d’une image (au lieu d’un conteneur actif), vous pouvez le faire:

docker run --rm cat>

Cela fera apparaître le conteneur, écrira le nouveau fichier, puis retirera le conteneur. Un inconvénient, cependant, est que les permissions de fichier et la date de modification ne seront pas préservées.

Créez un chemin où vous souhaitez copier le fichier, puis utilisez:

 docker run -d -v hostpath:dockerimag 

Créez un répertoire de données sur le système hôte (en dehors du conteneur) et montez-le dans un répertoire visible depuis l’intérieur du conteneur. Cela place les fichiers à un emplacement connu sur le système hôte et facilite l’access des fichiers et des outils aux applications et applications du système hôte.

 docker run -d -v /path/to/Local_host_dir:/path/to/docker_dir docker_image:tag