it-swarm.com.de

Kopieren von Dateien vom Docker-Container zum Host

Ich denke darüber nach, Docker zu verwenden, um meine Abhängigkeiten auf einem Continuous Integration-Server (CI) aufzubauen, damit ich nicht alle Laufzeiten und Bibliotheken auf den Agenten selbst installieren muss.

Um dies zu erreichen, müsste ich die Build-Artefakte, die im Container erstellt wurden, zurück in den Host kopieren. Ist das möglich?

1313
user2668128

Um eine Datei von einem Container auf den Host zu kopieren, können Sie den Befehl verwenden

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

Hier ist ein Beispiel:

$ Sudo docker cp goofy_roentgen:/out_read.jpg .

Hier ist goofy_roentgen der Name, den ich von folgendem Befehl erhalten habe:

$ 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
2321
creack

Sie müssen docker run nicht verwenden

Du kannst es mit docker create machen

Aus den Dokumenten Der Befehl docker create erstellt eine beschreibbare Containerebene über dem angegebenen Bild und bereitet sie auf die Ausführung des angegebenen Befehls vor. Die Container-ID wird dann in STDOUT gedruckt. Dies ähnelt dem Befehl docker run -d mit Ausnahme des Containers nie angefangen.

Sie können es also tun

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

Hier startet man nie den Container. Das hat mir gut getan.

96
Ishan Bhatt

Hängen Sie ein "Volume" ein und kopieren Sie die Artefakte dorthin:

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

Wenn der Build abgeschlossen ist und der Container nicht mehr ausgeführt wird, wurden die Artefakte bereits aus dem Build in das Verzeichnis artifacts auf dem Host kopiert.

Bearbeiten

Einschränkung: Wenn Sie dies tun, können Probleme auftreten, wenn die Benutzer-ID des Docker-Benutzers mit der Benutzer-ID des aktuell ausgeführten Benutzers übereinstimmt. Das heißt, die Dateien in /artifacts werden als Eigentum des Benutzers mit der UID des Benutzers angezeigt, der im Docker-Container verwendet wird. Ein Weg, dies zu umgehen, könnte darin bestehen, die UID des anrufenden Benutzers zu verwenden:

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
79
djhaskin987

Mounten Sie ein Volume, kopieren Sie die Artefakte, passen Sie die Eigentümer- und Gruppen-ID an:

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
23
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

Beschreibung

docker run mit einem Host-Volume, chown dem Artefakt, cp dem Artefakt auf dem Host-Volume:

$ 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

Dieser Trick funktioniert, weil der Aufruf von chown innerhalb von heredoc die Werte von $(id -u):$(id -g) außerhalb des laufenden Containers annimmt; der Docker-Host.

Die Vorteile sind:

  • du musst vorher nicht docker container run --name oder docker container create --name
  • sie müssen nicht danach docker container rm
22
rubicks

Wenn Sie keinen laufenden Container, nur ein Bild, haben und davon ausgehen, dass Sie nur eine Textdatei kopieren möchten, können Sie Folgendes tun:

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

Die meisten Antworten geben nicht an, dass der Container ausgeführt werden muss, bevor docker cp funktioniert:

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
12
cmcginty

Ich poste dies für jeden, der Docker für Mac verwendet. Das hat bei mir funktioniert:

 $ mkdir mybackup # local directory on Mac

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

Beachten Sie, dass beim Mounten mit -v automatisch das Verzeichnis backup erstellt wird.

Ich hoffe, dass dies eines Tages für jemanden nützlich ist. :)

7
Paul

Als allgemeinere Lösung es gibt ein CloudBees-Plugin für Jenkins, das in einem Docker-Container erstellt werden kann . Sie können ein Image zur Verwendung aus einer Docker-Registrierung auswählen oder eine Docker-Datei definieren, die erstellt und verwendet werden soll.

Der Arbeitsbereich wird als Volume in den Container eingebunden (mit dem entsprechenden Benutzer), als Arbeitsverzeichnis festgelegt und alle von Ihnen angeforderten Befehle werden ausgeführt (innerhalb des Containers). Sie können dazu auch das Docker-Workflow-Plugin (wenn Sie Code der Benutzeroberfläche vorziehen) mit dem Befehl image.inside () {} verwenden.

Im Grunde genommen ist dies alles in Ihren CI/CD-Server und noch einiges mehr eingebrannt.

4
BobMcGee
4
shuaihanhungry

Wenn Sie nur eine Datei aus einem Bild (anstelle eines laufenden Containers) ziehen möchten, können Sie dies tun:

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

Dadurch wird der Container aufgerufen, die neue Datei geschrieben und der Container entfernt. Ein Nachteil ist jedoch, dass die Dateiberechtigungen und das Änderungsdatum nicht erhalten bleiben.

3
s g

Ich habe PowerShell (Admin) mit diesem Befehl verwendet.

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

Beispiel

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

Sie können bind anstelle von volume verwenden, wenn Sie nur einen Ordner bereitstellen möchten und keinen speziellen Speicher für einen Container erstellen möchten:

  1. Bauen Sie Ihr Bild mit dem folgenden Tag:

    docker build . -t <image>

  2. Führen Sie Ihr Image aus und binden Sie das aktuelle Verzeichnis $ (pwd), in dem app.py gespeichert ist, und ordnen Sie es/root/example/in Ihrem Container zu.

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

0
zytfo

Erstellen Sie einen Pfad, in den Sie die Datei kopieren möchten, und verwenden Sie dann:

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