Copia di file dal contenitore Docker all’host

Sto pensando di usare Docker per build le mie dipendenze su un server di integrazione continua (CI), in modo da non dover installare tutti i runtime e le librerie sugli agenti stessi. Per ottenere ciò, dovrei copiare gli artefatti di build che sono stati creati all’interno del contenitore nell’host.

È ansible?

Per copiare un file da un contenitore all’host, puoi usare il comando

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

Ecco un esempio:

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

Qui goofy_roentgen è il nome che ho ricevuto dal seguente comando:

 [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 

Montare un “volume” e copiare gli artefatti in là:

 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 

Quindi, quando la compilazione termina e il contenitore non è più in esecuzione, ha già copiato le risorse dalla build nella directory delle risorse sull’host.

MODIFICARE:

CAVEAT: quando si esegue questa operazione, è ansible che si verifichino problemi con l’id utente dell’utente della finestra mobile che corrisponde all’ID utente dell’utente corrente in esecuzione. Cioè, i file in /artifacts verranno mostrati come di proprietà dell’utente con l’UID dell’utente utilizzato all’interno del contenitore finestra mobile. Un modo per aggirare questo potrebbe essere quello di utilizzare l’UID dell’utente chiamante:

 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 

Montare un volume, copiare gli artefatti, modificare l’ID proprietario e l’id del gruppo:

 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 <  

Più a lungo...

docker run con un volume host, chown l'artefatto, cp l'artefatto sul volume host:

 $ 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 

Questo trucco funziona perché l'invocazione chown all'interno di heredoc prende i valori $(id -u):$(id -g) dall'esterno del contenitore in esecuzione; cioè, l'host di docker.

I vantaggi rispetto alla docker cp sono:

  • non devi docker run --name tuo contenitore prima
  • non è necessario il docker container rm dopo

Se non si dispone di un contenitore in esecuzione, solo un’immagine e si presume che si desidera copiare solo un file di testo, è ansible fare qualcosa di simile:

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

Sto postando questo per chiunque stia usando Docker per Mac. Questo è ciò che ha funzionato per me:

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

Si noti che quando monto usando -v backup directory di backup viene creata automaticamente.

Spero che questo sia utile a qualcuno un giorno. 🙂

Non è necessario utilizzare la docker run

Puoi farlo con la docker create

Da documenti Il comando di creazione finestra mobile crea un livello contenitore scrivibile sull’immagine specificata e lo prepara per l’esecuzione del comando specificato. L’ID del contenitore viene quindi stampato su STDOUT. Questo è simile alla finestra mobile eseguire -d tranne che il contenitore non viene mai avviato.

Quindi, puoi farlo

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

Qui, non inizi mai il contenitore. Mi è sembrato vantaggioso.

La maggior parte delle risposte non indica che il contenitore deve essere eseguito prima che la docker cp funzioni:

 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 

Come soluzione più generale, c’è un plugin CloudBees per Jenkins da build all’interno di un contenitore Docker . È ansible selezionare un’immagine da utilizzare da un registro Docker o definire un Dockerfile da build e utilizzare.

Monta l’area di lavoro nel contenitore come un volume (con l’utente appropriato), lo imposta come directory di lavoro, esegue qualsiasi comando richiesto (all’interno del contenitore). Puoi anche usare il plugin docker-workflow (se preferisci il codice tramite interfaccia utente) per farlo, con il comando image.inside () {}.

Fondamentalmente tutto questo, cotto nel tuo server CI / CD e poi in alcuni.

Se vuoi solo estrarre un file da un’immagine (invece che da un contenitore in esecuzione) puoi farlo:

docker run --rm cat>

Questo farà apparire il contenitore, scriverà il nuovo file, quindi rimuoverà il contenitore. Uno svantaggio, tuttavia, è che le autorizzazioni del file e la data di modifica non verranno conservate.

Creare un percorso in cui si desidera copiare il file e quindi utilizzare:

 docker run -d -v hostpath:dockerimag 

Creare una directory di dati sul sistema host (all’esterno del contenitore) e montarla in una directory visibile all’interno del contenitore. Ciò colloca i file in una posizione nota sul sistema host e facilita l’accesso ai file agli strumenti e alle applicazioni sul sistema host

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