web-dev-qa-db-fra.com

Copier des fichiers d'un conteneur Docker vers un hôte

Je songe à utiliser Docker pour créer mes dépendances sur un serveur d'intégration continue (CI), de sorte que je n'ai pas à installer toutes les bibliothèques d'exécution et les bibliothèques sur les agents eux-mêmes.

Pour ce faire, je devrais copier les artefacts de construction construits à l'intérieur du conteneur dans l'hôte. Est-ce possible?

1228
user2668128

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

docker cp <containerId>:/file/path/within/container /Host/path/target

Voici un exemple:

$ Sudo docker cp goofy_roentgen:/out_read.jpg .

Ici goofy_roentgen est le nom que j'ai obtenu avec la commande suivante:

$ Sudo docker ps

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
2179
creack

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 <artifact> /artifacts
# ... copy more artifacts into `/artifacts` ...
COMMANDS

Ensuite, lorsque la construction est terminée et que le conteneur n'est plus en cours d'exécution, il a déjà copié les artefacts de la construction dans le répertoire artifactsde l'hôte.

Modifier

Caveat: Dans ce cas, vous pouvez rencontrer des problèmes avec l'ID utilisateur de l'utilisateur docker correspondant à l'ID utilisateur de l'utilisateur en cours d'exécution. C'est-à-dire que les fichiers de /artifacts seront affichés comme appartenant à l'utilisateur avec l'UID de l'utilisateur utilisé dans le conteneur de menu fixe. Une solution consiste à 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
76
djhaskin987

Vous n'avez pas besoin d'utiliser docker run

Vous pouvez le faire avec docker create

A partir de la documentation La commande docker create crée un calque de conteneur inscriptible sur l'image spécifiée et la prépare pour l'exécution de la commande spécifiée. L'ID de conteneur est ensuite imprimé sur STDOUT. Cette opération est similaire à docker run -d, sauf que le conteneur est jamais commencé.

Alors tu peux 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.

51
Ishan Bhatt

Montez un volume, copiez les artefacts, ajustez l'identifiant du propriétaire et l'identifiant 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
20
Dimchansky

TLDR;

$ docker run --rm -iv${PWD}:/Host-volume my-image sh -s <<EOF
chown $(id -u):$(id -g) my-artifact.tar.xz
cp -a my-artifact.tar.xz /Host-volume
EOF

La description

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

$ docker build -t my-image - <<EOF
> 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 <<EOF
chown -v $(id -u):$(id -g) *.txt
cp -va *.txt /Host-volume
EOF
changed ownership of '/Host-volume/bar.txt' to 10335:11111
changed ownership of '/Host-volume/qux.txt' to 10335:11111
changed ownership of '/Host-volume/foo.txt' to 10335:11111
'bar.txt' -> '/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 car l'invocation chown au sein des valeurs heredoc the prend $(id -u):$(id -g) de l'extérieur du conteneur en cours d'exécution; c'est-à-dire l'hôte de docker.

Les avantages sont:

  • vous n'avez pas à docker container run --name ou docker container create --name avant
  • vous n'avez pas à docker container rm après
17
rubicks

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

docker run the-image cat path/to/container/file.txt > path/to/Host/file.txt
13
cancerbero

La plupart des réponses n'indiquent pas que le conteneur doit être exécuté avant que docker cp 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
10
cmcginty

Je poste ceci pour quiconque utilise Docker pour Mac. C'est ce qui a fonctionné pour moi:

 $ mkdir mybackup # local directory on Mac

 $ docker run --rm --volumes-from <containerid> \
    -v `pwd`/mybackup:/backup \  
    busybox \                   
    cp /data/mydata.txt /backup 

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

J'espère que cela sera utile à quelqu'un un jour. :)

6
Paul
4
shuaihanhungry

Comme solution plus générale, il existe un plugin CloudBees que Jenkins peut construire à l'intérieur d'un conteneur Docker . Vous pouvez sélectionner une image à utiliser dans un registre Docker ou définir un fichier Docker à créer et à utiliser.

Il monte l'espace de travail dans le conteneur en tant que volume (avec l'utilisateur approprié), le définit comme votre répertoire de travail et exécute les commandes que vous demandez (à l'intérieur du conteneur). Vous pouvez également utiliser le plug-in docker-workflow (si vous préférez le code sur l'interface utilisateur) pour ce faire, avec la commande image.inside () {}.

En gros, tout cela est intégré à votre serveur CI/CD, puis à d’autres.

3
BobMcGee

Si vous voulez simplement extraire un fichier d'un image (au lieu d'un conteneur en cours d'exécution), vous pouvez faire ceci:

docker run --rm <image> cat <source> > <local_dest>

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

3
s g

J'ai utilisé PowerShell (Admin) avec cette commande.

docker cp {container id}:{container path}/error.html  C:\\error.html

Exemple

docker cp ff3a6608467d:/var/www/app/error.html  C:\\error.html
2

Vous pouvez utiliser bind au lieu de volume si vous voulez monter un seul dossier, sans créer de stockage spécial pour un conteneur:

  1. Construisez votre image avec la balise:

    docker build . -t <image>

  2. Exécutez votre image et liez le répertoire $ (pwd) actuel où app.py est stocké et mappez-le sur/root/example/à l'intérieur de votre conteneur.

    docker run --mount type=bind,source="$(pwd)",target=/root/example/ <image> python app.py

0
zytfo

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

docker run -d -v hostpath:dockerimag
0
Chandra Pal