Copie de fichiers de l'hôte vers le conteneur Docker

1582

J'essaie de créer une solution de sauvegarde et de restauration pour les conteneurs Docker avec lesquels nous travaillons.

J'ai une image de base Docker que j'ai créée, ubuntu:baseet je ne veux pas avoir à la reconstruire à chaque fois avec un fichier Docker pour y ajouter des fichiers.

Je veux créer un script qui s'exécute à partir de la machine hôte et crée un nouveau conteneur à l'aide de l' ubuntu:baseimage Docker, puis copie des fichiers dans ce conteneur.

Comment puis-je copier des fichiers de l'hôte vers le conteneur?

user3001829
la source
12
Si vous ne voulez pas reconstruire, pourquoi ne pas " docker commit "? Cela enregistre votre image.
Berend de Boer
28
Juste une remarque sur une notion que personne n'a abordée: en général, traitez les conteneurs comme "éphémères". Il existe des cas d'utilisation pour copier des fichiers dans / à partir d'un conteneur en cours d'exécution (test, prototypage). Mais si vous vous retrouvez dans une position où vous ne pouvez pas reconstruire ce dont vous avez besoin en utilisant Dockerfiles et / ou composer, alors vous pouvez être au mauvais endroit. En règle générale, vous ne voulez pas sauvegarder des conteneurs comme s'il s'agissait d'OS ou même d'objets VM. De manière générale :-)
Scott Prive
Copie
Shubham

Réponses:

2676

le cp commande peut être utilisée pour copier des fichiers.

Un fichier spécifique peut être copié dans le conteneur comme:

docker cp foo.txt mycontainer:/foo.txt

Un fichier spécifique peut être copié DU conteneur comme:

docker cp mycontainer:/foo.txt foo.txt

Pour mettre l'accent, mycontainerest un ID de conteneur , pas une image ID d' .

Plusieurs fichiers contenus dans le dossier srcpeuvent être copiés dans le targetdossier en utilisant:

docker cp src/. mycontainer:/target
docker cp mycontainer:/src/. target

Référence: documentation Docker CLI pourcp

Dans les versions Docker antérieures à la version 1.8, il était uniquement possible de copier des fichiers d'un conteneur vers l'hôte. Pas de l'hôte vers un conteneur.

0x7d7b
la source
2
notez également que cela peut être sur l'hôte vm ou le système d'exploitation principal et fonctionne soit hôte vers conteneur ou vm pour héberger (ou os principal)
Adam Tuliper - MSFT
7
Dans un Dockerfile, vous pouvez utiliser le mot clé ADD pour ajouter des fichiers pendant la construction.
0x7d7b
4
@ h3nrik COPYpréféré par rapport à leADD cas échéant.
Franklin Yu
10
utiliser docker cppour copier du conteneur vers l'hôte fonctionne bien, mais quand l'utiliser pour copier des fichiers de l'hôte vers le conteneur, aucun effet ... quelqu'un sait pourquoi? version docker: Docker version 1.10.3, build cb079f6-
unsupported
2
Puis-je copier plusieurs fichiers à l'aide de Docker CP de l'hôte vers le conteneur?
Yogesh
182
  1. Obtenez le nom du conteneur ou l'ID court du conteneur:

    $ docker ps
    
  2. Obtenez l'identifiant complet du conteneur:

    $ docker inspect -f   '{{.Id}}'  SHORT_CONTAINER_ID-or-CONTAINER_NAME
    
  3. Copier un fichier:

    $ sudo cp path-file-host /var/lib/docker/aufs/mnt/FULL_CONTAINER_ID/PATH-NEW-FILE
    

EXEMPLE:

$ docker ps

CONTAINER ID      IMAGE    COMMAND       CREATED      STATUS       PORTS        NAMES

d8e703d7e303   solidleon/ssh:latest      /usr/sbin/sshd -D                      cranky_pare

$ docker inspect -f   '{{.Id}}' cranky_pare

ou

$ docker inspect -f   '{{.Id}}' d8e703d7e303

d8e703d7e3039a6df6d01bd7fb58d1882e592a85059eb16c4b83cf91847f88e5

$ sudo cp file.txt /var/lib/docker/aufs/mnt/**d8e703d7e3039a6df6d01bd7fb58d1882e592a85059eb16c4b83cf91847f88e5**/root/file.txt
Solidleon
la source
13
Pour moi, le chemin de montage de l'hôte ne contenait aufsqu'un a devicemapper. Le moyen le plus simple de vérifier le chemin de montage des conteneurs (pendant qu'il est en cours d'exécution) consiste à exécuter la commande mount.
derenio
3
J'ai essayé la solution ci-dessus. Il a copié les fichiers dans le répertoire spécifique du docker. Cependant, lorsque j'utilise bash pour le docker, les fichiers ne s'affichent pas là-bas. Y a-t-il quelque chose qui me manque?
AppleBud
2
Le nouveau chemin est / var / lib / docker / devicemapper / mnt / <<id>> / rootfs /
mcuadros
4
Pour moi, sur Docker 1.4.1 (dernière version actuelle), c'est/var/lib/docker/aufs/diff/<id>/
user193130
3
qu'en est-il pour les pauvres utilisateurs de MacOS? Le répertoire de montage est /var/libpour moi. find / -name dockern'était pas utile non plus.
Prayagupd
141

La manière la plus propre consiste à monter un répertoire hôte sur le conteneur lors du démarrage du conteneur:

{host} docker run -v /path/to/hostdir:/mnt --name my_container my_image
{host} docker exec -it my_container bash
{container} cp /mnt/sourcefile /path/to/destfile
Ben Davis
la source
3
comment pouvez-vous exécuter le conteneur? je pensais que vous ne pouvez le faire qu'avec une image.
Pavel Zaitsev
Je ne peux pas le faire fonctionner lorsque le conteneur existe, c'est-à-dire qu'il a déjà fonctionné. Le goudron ci-dessous fonctionne bien.
Eino Mäkitalo
1
La seule façon dont cela a fonctionné pour moi était d'attacher le volume à côté de l'exécution de l'image (instancier le conteneur). Se sont retrouvés avec:docker run -d -p -v /host/path:/mnt --name container_name image_name
peter n
2
Cela ne fonctionne pas pour moi. Atleast ne peut pas exécuter de conteneur. Peut exécuter uniquement l'image
Shashank Hegde
1
Je suis étonné que ce docker cpsoit une opération à sens unique!
ThorSummoner
115

Ce qui suit est une façon assez laide de le faire, mais cela fonctionne.

docker run -i ubuntu /bin/bash -c 'cat > file' < file
Erik
la source
7
Cela fonctionne très bien! Mais ne pas oublier de valider le changement: docker commit `docker ps -l -q` ubuntu-with-file. Sinon, le changement sera perdu (utilisez le nom de votre choix à la place ubuntu-with-file)
Michael_Scharf
@Erik: Où se trouvait le fichier lors de l'exécution du conteneur?
coanor
49
De plus, nous pouvons utiliser une nouvelle docker execfonctionnalité pour travailler avec le conteneur en cours d'exécution:docker exec -it <container_id> bash -c 'cat > /path/to/container/file' < /path/to/host/file/
Mikl
17
@Mikl Je pense qu'il devrait être au docker exec -i ...lieu de -it, parce qu'il n'y a pas d' ATS lorsque la tuyauterie dans un fichier.
z0r
4
Si vous êtes toujours bloqué sur une ancienne version de Docker (comme je le suis) et que vous souhaitez copier un répertoire entier, vous pouvez le faire: tar -c -v -f - /path/to/host/directory | docker exec -i <container-name> bash -c 'tar -x -v --strip-components 1 -f - -C /path/to/container/directory'
eahanson
43

Si vous devez le faire sur un conteneur en cours d'exécution, vous pouvez utiliser le docker exec (ajouté en 1.3).

Tout d'abord, recherchez le nom ou l'ID du conteneur:

$ docker ps
CONTAINER ID        IMAGE                        COMMAND             CREATED             STATUS              PORTS                   NAMES
b9b7400ddd8f        ubuntu:latest                "/bin/bash"         2 seconds ago       Up 2 seconds                                elated_hodgkin

Dans l'exemple ci-dessus, nous pouvons utiliser b9b7400ddd8fouelated_hodgkin .

Si vous vouliez tout copier /tmp/somefilessur l'hôte /var/wwwdans le conteneur:

$ cd /tmp/somefiles
$ tar -cv * | docker exec -i elated_hodgkin tar x -C /var/www

Nous pouvons ensuite exécuter /bin/bashdans le conteneur et vérifier que cela a fonctionné:

$ docker exec -it elated_hodgkin /bin/bash
root@b9b7400ddd8f:/# ls /var/www
file1  file2
adean
la source
Fonctionne très bien sur docker 1.16 sur Centos 7.4 Grande idée innovante.
Dudi Boy
41
  1. Créez un nouveau dockerfile et utilisez l'image existante comme base.

    FROM myName/myImage:latest
    
    ADD myFile.py bin/myFile.py
    
  2. Construisez ensuite le conteneur:

    docker build .
    
RustyShackleford
la source
2
C'est ce qui a fonctionné pour moi. Rien d'autre. Je vous remercie!
Owen
Il créera une nouvelle image, pas directement un nouveau conteneur. Si vous réutilisez cette image alors que monFichier.py est modifié, il utilisera l'ancienne version du fichier, sauf si vous reconstruisez l'image.
Guillaume Lebreton
Je trouve cela le moyen le plus rapide uniquement si vous testez sur un serveur distant.
Dominik Krulak
Selon cela, la plupart des gens devraient utiliser COPY plutôt que ADD. Mais pour les fichiers locaux (comme dans cet exemple), ils sont équivalents.
hoosierEE
39

La solution est donnée ci-dessous,

Depuis le shell Docker,

root@123abc:/root#  <-- get the container ID

De l'hôte

cp thefile.txt /var/lib/docker/devicemapper/mnt/123abc<bunch-o-hex>/rootfs/root

Le fichier doit être directement copié à l'emplacement où se trouve le conteneur sur le système de fichiers.

transpercer
la source
10
Très bonne réponse. Dans les nouvelles versions de docker, le chemin a été renommé en / var / lib / docker / aufs / mnt /
Alex Volkov
le chemin devicemapper ne semble pas fonctionner sur fedora avec docker 1.6. Je l'ai mis en tant que Q séparé, stackoverflow.com/questions/29939419/… , tout commentaire serait apprécié.
Yogesh_D
33

Il existe généralement trois types:

  1. Du conteneur à l'hôte

    docker cp container_id:./bar/foo.txt .
    

dev1

  1. De l'hôte à un conteneur

    docker exec -i container_id sh -c 'cat > ./bar/foo.txt' < ./foo.txt
    

dev2

  1. D'un récipient à un récipient mélange 1 et 2

    docker cp container_id1:./bar/foo.txt .
    
    docker exec -i container_id2 sh -c 'cat > ./bar/foo.txt' < ./foo.txt
    

dev3

Ali Hallaji
la source
6
docker cp fonctionne dans les deux sens. Pas besoin d'exec, cat et redirect. docker cp host_file.txt container: / path /
tbm
32

Une autre solution pour copier des fichiers dans un conteneur en cours d'exécution utilise tar:

tar -c foo.sh | docker exec -i theDockerContainer /bin/tar -C /tmp -x

Copie le fichier foo.shdans/tmp le conteneur.

Edit: Supprimez reduntant -f, grâce au commentaire de Maarten .

joemat
la source
C'est bien si vous devez envoyer un répertoire entier. Pour un seul fichier, la réponse d'Erik est plus simple.
Kelvin
1
@Kelvin: Mais tar conserve également les attributs et le nom des fichiers. Entre autres, cela signifie que vous n'avez qu'à taper le nom une fois (et vous obtenez l'achèvement de l'onglet à partir de votre shell). Je dirais donc que tar est en fait plus simple, tant qu'il est installé dans le conteneur.
Maarten
1
C'est -f -un peu redondant cependant, le comportement par défaut est quand même d'écrire sur stdout.
Maarten
cela signifie qu'il existe une dépendance de l'hôte sur le goudron
cellige
Vous avez raison - vous devez installer tar sur l'hôte et dans le conteneur. De nos jours, utiliser Docker cp est la meilleure solution.
joemat
24

Pour copier un fichier de l'hôte vers le conteneur en cours d'exécution

docker exec -i $CONTAINER /bin/bash -c "cat > $CONTAINER_PATH" < $HOST_PATH

Basé sur la réponse d'Erik et les commentaires de Mikl et z0r.

Andrea
la source
Les solutions acceptées perturbent parfois l'indentation des fichiers lors du transfert vers des conteneurs en cours d'exécution. Cela fonctionne parfaitement pour de tels cas
Dreams
15

Il s'agit d'une réponse directe à la question «Copie de fichiers de l'hôte vers le conteneur Docker» soulevée dans cette question dans le titre.

Essayez docker cp. C'est le moyen le plus simple de le faire et fonctionne même sur mon Mac. Usage:

docker cp /root/some-file.txt some-docker-container:/root

Cela copiera le fichier some-file.txtdans le répertoire /rootde votre machine hôte dans le conteneur Docker nommé some-docker-containerdans le répertoire/root . Il est très proche de la syntaxe de copie sécurisée. Et comme indiqué dans le post précédent, vous pouvez l'utiliser inversement. C'est-à-dire que vous copiez également des fichiers du conteneur vers l'hôte.

Et avant de télécharger ce post, veuillez saisir docker cp --help . La lecture de la documentation peut être très utile, parfois ...

Si vous n'aimez pas de cette façon et que vous voulez des volumes de données dans votre conteneur déjà créé et en cours d'exécution, la récréation est votre seule option aujourd'hui. Voir aussi Comment puis-je ajouter un volume à un conteneur Docker existant? .

Hiro.Protagonist
la source
15

J'ai essayé la plupart des solutions (votées) ici, mais dans docker 17.09 (en 2018), il n'y a plus de dossier / var / lib / docker / aufs.

Ce simple a docker cprésolu cette tâche.

docker cp c:\path\to\local\file container_name:/path/to/target/dir/

Comment obtenir container_name?

 docker ps 

Il y a une NAMESsection. N'utilisez pas a IMAGE.

Aerin
la source
12

Pour copier des fichiers / dossiers entre un conteneur et le système de fichiers local, tapez la commande:

docker cp {SOURCE_FILE} {DESTINATION_CONTAINER_ID}:/{DESTINATION_PATH}

Par exemple,

docker cp /home/foo container-id:/home/dir

Pour obtenir l'ID contianer, tapez la commande donnée:

docker ps

Le contenu ci-dessus provient de docker.com .

Prayagupd
la source
8

En supposant que le conteneur est déjà en cours d'exécution, tapez la commande donnée:

# cat /path/to/host/file/ | docker exec -i -t <container_id> bash -c "/bin/cat > /path/to/container/file"

Pour partager des fichiers à l'aide d'un répertoire partagé, exécutez le conteneur en tapant la commande donnée:

# docker run -v /path/to/host/dir:/path/to/container/dir ...

Remarque: des problèmes d'autorisations peuvent survenir car les utilisateurs du conteneur ne sont pas les mêmes que ceux de l'hôte.

johndodo
la source
1
En plus:docker exec -it <container_id> bash -c 'cat > /path/to/container/file' < /path/to/host/file/
Mikl
2
Notez que catce ne sera pas résilié une fois qu'il se termine. Si cela vous importe (si vous copiez des scripts bash, bash refusera de les exécuter), vous devez exécuter lsof | grep yourfilenameet tuer le catprocessus qui contient ledit fichier.
johndodo
THX! Bon conseil. Pouvez-vous me dire comment tuer ce processus avec une seule commande? Quelque chose comme kill $(lsof | grep /path/to/file | sed ...). Je serai reconnaissant pour votre aide
Mikl
kill $(docker top CONTAINERNAME | sed -n '/cat$/p' | sed 's/^root[^0-9]\+\([0-9]\+\).*$/\1/')
Mikl
8

Il s'agit de la commande pour copier les données de Docker vers l'hôte:

docker cp container_id:file path/filename /hostpath

docker cp a13fb9c9e674:/tmp/dgController.log /tmp/

Vous trouverez ci-dessous la commande pour copier les données de l'hôte vers le docker:

docker cp a.txt ccfbeb35116b:/home/
Maninder
la source
7

Dans un environnement docker, tous les conteneurs se trouvent dans le répertoire:

/var/lib/docker/aufs/required-docker-id/

Pour copier le répertoire / fichier source dans n'importe quelle partie du conteneur, tapez la commande donnée:

sudo cp -r mydir/ /var/lib/docker/aufs/mnt/required-docker-id/mnt/

0x3bfc
la source
5

taret docker cpsont un bon combo pour tout copier dans un répertoire.

Créer un conteneur de volume de données

docker create --name dvc --volume /path/on/container cirros

Pour conserver la hiérarchie des répertoires

tar -c -C /path/on/local/machine . | docker cp - dvc:/path/on/container

Vérifie ton travail

docker run --rm --volumes-from dvc cirros ls -al /path/on/container
Everett Toews
la source
5

Si l'hôte est CentOS ou Fedora, il n'y a pas de proxy /var/lib/docker/aufs, mais il est sous /proc:

cp -r /home/user/mydata/* /proc/$(docker inspect --format "{{.State.Pid}}" <containerid>)/root

Cette cmd copiera tout le contenu du datarépertoire dans le /conteneur avec l'ID "containerid".

Abdennour TOUMI
la source
Ce n'est pas unique à Redhat: cela fonctionne aussi sur Debian. (peut-être tous Gnu / Linux avec /proc). Étendez également le chemin pour placer le fichier ailleurs, pas seulement root.
ctrl-alt-delor
5

mycontainerSi quelqu'un comme moi ne sait pas ce que signifie la réponse @ h3nrik, il s'agit en fait de l'ID du conteneur. Pour copier un fichier WarpSquare.mp4dans /app/example_scenes/1440p60d'un conteneur docker dans le dossier en cours est sorti je cela.

docker cp `docker ps -q -l`:/app/example_scenes/1440p60/WarpSquare.mp4 .

docker ps -q -lextrait l'ID de conteneur de la dernière instance terminée. Si ce n'est pas un conteneur sorti, vous pouvez le récupérer docker container lsoudocker ps

ishandutta2007
la source
1
Vous pouvez répertorier les identifiants des conteneurs sortis avec docker ps -aou docker container ls -a.
0x7d7b
4

Beaucoup de ceux qui trouvent cette question peuvent avoir le problème de copier des fichiers dans une image Docker pendant sa création (je l'ai fait).

Dans ce cas, vous pouvez utiliser la COPYcommande dans la Dockerfileque vous utilisez pour créer l'image.

Consultez la documentation .

Klas Mellbourn
la source
4

Vous pouvez simplement tracer l'adresse IP de votre machine locale en utilisant

ifconfig

Ensuite, entrez simplement dans votre conteneur Docker et tapez

scp user_name@ip_address:/path_to_the_file destination

Dans tous les cas, si vous n'avez pas de client et de serveur SSH installé, installez-le simplement en utilisant:

sudo apt-get install openssh-server
Harshit Anand
la source
Merci beaucoup, cela a bien fonctionné pour moi. De plus, je l'ai trouvé plus efficace que les autres moyens
user1314742
Il s'agit d'une horrible solution en termes de sécurité.
4

Il s'agit d'un onliner pour copier un seul fichier lors de l'exécution d'un conteneur tomcat.

docker run -v /PATH_TO_WAR/sample.war:/usr/local/tomcat/webapps/myapp.war -it -p 8080:8080 tomcat

Cela copiera le fichier war dans le répertoire webapps et fera fonctionner votre application en un rien de temps.

karthik101
la source
1
-v va monter (c'est-à-dire créer un lien), pas copier
Vitaliy Ulantikov
la différence dans le résultat est que le montage masque le contenu du conteneur précédent, par exemple, si vous montez un dossier hôte sur un dossier de conteneur, vous ne pouvez plus voir le contenu du dossier de conteneur précédent
mrq
4

Syntaxe de Container Up:

 docker run -v /HOST/folder:/Container/floder 

Dans le fichier Docker

COPY hom* /myFolder/        # adds all files starting with "hom"
COPY hom?.txt /myFolder/    # ? is replaced with any single character, e.g., "home.txt"
Isura Nimalasiri
la source
3

La meilleure façon de copier des fichiers dans le conteneur que j'ai trouvé est de monter un répertoire sur l'hôte en utilisant l' -voption de la commande docker run.

Prakash Varandani
la source
3

Il y a de bonnes réponses, mais trop spécifiques. Je trouve que docker psc'est un bon moyen d'obtenir l'identifiant du conteneur qui vous intéresse.

mount | grep <id>

pour voir où le volume est monté. C'est

/var/lib/docker/devicemapper/mnt/<id>/rootfs/

pour moi, mais ce pourrait être un chemin différent selon le système d'exploitation et la configuration. Maintenant, copiez simplement les fichiers sur ce chemin.

L'utilisation -vn'est pas toujours pratique.

akostadinov
la source
3

Je viens de commencer à utiliser Docker pour compiler VLC, voici ce que vous pouvez faire pour copier des fichiers dans les deux sens à partir de conteneurs:

su -
cd /var/lib/docker
ls -palR > /home/user/dockerfilelist.txt

Recherchez un fichier familier dans ce txt et vous aurez le dossier, cd-y en tant que root et le tour est joué! copiez tout ce que vous voulez.

Il pourrait y avoir un chemin avec "fusionné" dedans, je suppose que vous voulez celui avec "diff" dedans.

De plus, si vous quittez le conteneur et que vous souhaitez revenir là où vous vous étiez arrêté:

docker ps -a
docker start -i containerid

Je suppose que c'est utile quand vous n'avez rien nommé avec une commande comme

docker run -it registry.videolan.org:5000/vlc-debian-win64 /bin/bash

Bien sûr, la méthode de piratage, mais alors quoi!

colin lamarre
la source
3
docker cp SRC_PATH CONTAINER_ID:DEST_PATH

Par exemple, je veux copier mon fichier xxxx / download / jenkins sur tomcat

Je commence à obtenir l'identifiant du conteneur Tomcat

docker ps

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
63686740b488        tomcat              "catalina.sh run"   12 seconds ago      Up 11 seconds       0.0.0.0:8080->8080/tcp   peaceful_babbage

docker cp xxxx/download/jenkins.war  63686740b488:usr/local/tomcat/webapps/
Mourad MAMASSI
la source
2

Ma méthode préférée:

CONTENANTS:

CONTAINER_ID=$(docker ps | grep <string> | awk '{ print $1 }' | xargs docker inspect -f '{{.Id}}')

file.txt

mv -f file.txt /var/lib/docker/devicemapper/mnt/$CONTAINER_ID/rootfs/root/file.txt

ou

mv -f file.txt /var/lib/docker/aufs/mnt/$CONTAINER_ID/rootfs/root/file.txt
user3159411
la source
le chemin devicemapper ne semble pas fonctionner sur fedora avec docker 1.6. Je l'ai mis en tant que Q séparé, stackoverflow.com/questions/29939419/… , tout commentaire serait apprécié.
Yogesh_D
2

À mon avis, vous ne devez pas copier les fichiers à l'intérieur de l'image, mais vous pouvez utiliser GIT ou SVN pour vos fichiers, puis définir un volume synchronisé avec un dossier local. Utilisez un script lors de l'exécution du conteneur qui peut vérifier si les données existent déjà dans le dossier local sinon les copier depuis le référentiel GIT. Cela rend votre image très légère.

h.aittamaa
la source
Cela semble être un risque pour la sécurité et un cauchemar d'accès en attente de se produire. Comment donnez-vous accès au référentiel git depuis votre image? Même en supposant qu'il s'agit d'un référentiel public, vous allez supposer que l'hôte sur lequel votre conteneur s'exécute a accès à ce référentiel.
tbm
Je suis d'accord avec vous si git est utilisé dans le conteneur docker. Mais dans notre cas, le script s'exécute à partir de la machine hôte
h.aittamaa