Copiar archivos del host al contenedor Docker

1581

Estoy tratando de crear una solución de respaldo y restauración para los contenedores Docker con los que trabajamos.

Tengo la imagen base de Docker que he creado, ubuntu:basey no quiero tener que reconstruirla cada vez con un archivo Docker para agregarle archivos.

Quiero crear un script que se ejecute desde la máquina host y cree un nuevo contenedor con la ubuntu:baseimagen de Docker y luego copie los archivos en ese contenedor.

¿Cómo puedo copiar archivos del host al contenedor?

usuario3001829
fuente
12
Si no desea reconstruir, ¿por qué no " docker commit "? Eso salva tu imagen.
Berend de Boer
28
Solo una observación sobre una noción que nadie ha abordado: en general, trate los contenedores como "efímeros". Hay casos de uso para copiar archivos en / desde un contenedor en ejecución (pruebas, creación de prototipos). Pero si te encuentras en una posición en la que no puedes reconstruir lo que necesitas usando Dockerfiles y / o componer, entonces puedes estar en un mal lugar. Por lo general, no desea hacer una copia de seguridad de los contenedores como si fueran SO o incluso objetos de VM. En términos generales :-)
Scott Prive
Posible duplicado de Copiar archivos del contenedor Docker al host
Shubham

Respuestas:

2674

El cpcomando se puede usar para copiar archivos.

Se puede copiar un archivo específico AL contenedor como:

docker cp foo.txt mycontainer:/foo.txt

Se puede copiar un archivo específico del contenedor como:

docker cp mycontainer:/foo.txt foo.txt

Para enfatizar, mycontaineres una ID de contenedor , no una ID de imagen .

Se srcpueden copiar varios archivos contenidos en la carpeta en la targetcarpeta usando:

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

Referencia: documentos de Docker CLI paracp

En las versiones de Docker anteriores a la 1.8 solo era posible copiar archivos de un contenedor al host. No desde el host a un contenedor.

0x7d7b
fuente
2
también tenga en cuenta que esto puede estar en el host vm o el sistema operativo principal y funciona de host a contenedor o vm a host (o sistema operativo principal)
Adam Tuliper - MSFT
77
En un Dockerfile puede usar la palabra clave ADD para agregar archivos durante el tiempo de compilación.
0x7d7b
44
@ h3nrik COPYprefiere sobreADD cuando corresponde.
Franklin Yu
10
usar docker cppara copiar del contenedor al host funciona bien, pero cuando se usa para copiar archivos del host al contenedor, no tiene efecto ... ¿alguien sabe por qué? versión docker: Docker versión 1.10.3, compilación cb079f6-
unsupported
2
¿Puedo copiar múltiples archivos usando docker cp del host al contenedor?
Yogesh
182
  1. Obtener el nombre del contenedor o el ID del contenedor corto:

    $ docker ps
    
  2. Obtener la identificación del contenedor completo:

    $ docker inspect -f   '{{.Id}}'  SHORT_CONTAINER_ID-or-CONTAINER_NAME
    
  3. Copiar archivo:

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

EJEMPLO:

$ 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

o

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

d8e703d7e3039a6df6d01bd7fb58d1882e592a85059eb16c4b83cf91847f88e5

$ sudo cp file.txt /var/lib/docker/aufs/mnt/**d8e703d7e3039a6df6d01bd7fb58d1882e592a85059eb16c4b83cf91847f88e5**/root/file.txt
solidleon
fuente
13
Para mí, el camino de montaje del anfitrión no contenía aufssino a devicemapper. La forma más fácil de verificar la ruta de montaje de los contenedores (mientras se está ejecutando) es ejecutar el comando mount.
derenio
3
Probé la solución anterior. Copió los archivos en el directorio específico de la ventana acoplable. Sin embargo, cuando uso bash para el contenedor docker, los archivos no aparecen allí. Hay algo que este olvidando ?
AppleBud
2
La nueva ruta es / var / lib / docker / devicemapper / mnt / <<id>> / rootfs /
mcuadros el
44
Para mí, en Docker 1.4.1 (actual más reciente), es/var/lib/docker/aufs/diff/<id>/
user193130
3
¿Qué pasa con los usuarios pobres de MacOS? El directorio de montaje está /var/libpara mí. find / -name dockertampoco fue útil.
prayagupd
141

La forma más limpia es montar un directorio de host en el contenedor al iniciar el contenedor:

{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
fuente
3
¿Cómo puedes ejecutar el contenedor? Pensé que solo se podía hacer eso con una imagen.
Pavel Zaitsev
No puedo hacer que funcione cuando el contenedor ya existe, también se ha ejecutado antes. Tar abajo funciona bien.
Eino Mäkitalo
1
La única forma en que esto funcionó para mí fue adjuntando el volumen junto con la ejecución de la imagen (instanciando el contenedor). Terminó con:docker run -d -p -v /host/path:/mnt --name container_name image_name
Peter n
2
Esto no funciona para mí. Al menos no puede ejecutar un contenedor. Solo se puede ejecutar la imagen
Shashank Hegde
1
¡Estoy sorprendido de que docker cpsea ​​una operación unidireccional!
ThorSummoner
115

La siguiente es una forma bastante fea de hacerlo, pero funciona.

docker run -i ubuntu /bin/bash -c 'cat > file' < file
Erik
fuente
77
¡Esto funciona muy bien! Pero no se olvide de confirmar el cambio: docker commit `docker ps -l -q` ubuntu-with-file. De lo contrario, el cambio se perderá (use el nombre que desee en lugar de ubuntu-with-file)
Michael_Scharf
@Erik: ¿Dónde se encuentra el archivo cuando se ejecuta el contenedor?
coanor
49
Además, podemos usar una nueva docker execfunción para trabajar con el contenedor en ejecución:docker exec -it <container_id> bash -c 'cat > /path/to/container/file' < /path/to/host/file/
Mikl
17
@Mikl, creo que debería ser en docker exec -i ...lugar de -it, porque no hay TTY cuando se conecta desde un archivo.
z0r
44
Si todavía está atascado en una versión antigua de Docker (como yo) y quiere copiar un directorio completo, puede hacer esto: 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 necesita hacer esto en un contenedor en ejecución, puede usar docker exec (agregado en 1.3).

Primero, encuentre el nombre o ID del contenedor:

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

En el ejemplo anterior, podemos usar b9b7400ddd8fo elated_hodgkin.

Si desea copiar todo en /tmp/somefilesel host /var/wwwen el contenedor:

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

Luego podemos ejecutar /bin/bashen el contenedor y verificar que funcionó:

$ docker exec -it elated_hodgkin /bin/bash
root@b9b7400ddd8f:/# ls /var/www
file1  file2
adean
fuente
Funciona muy bien en Docker 1.16 en Centos 7.4 Gran idea innovadora.
Dudi Boy
41
  1. Cree un nuevo dockerfile y use la imagen existente como base.

    FROM myName/myImage:latest
    
    ADD myFile.py bin/myFile.py
    
  2. Luego construya el contenedor:

    docker build .
    
RustyShackleford
fuente
2
Esto es lo que funcionó para mí. Nada más. ¡Gracias!
Owen
Creará una nueva imagen, no directamente un nuevo contenedor. Si reutiliza esta imagen mientras myFile.py se modifica, utilizará la versión anterior del archivo, a menos que reconstruya la imagen.
Guillaume Lebreton
Me parece la forma más rápida solo si está probando en un servidor remoto.
Dominik Krulak
De acuerdo con esto, la mayoría de las personas deberían usar COPIA en lugar de AGREGAR. Pero para los archivos locales (como en este ejemplo) son equivalentes.
hoosierEE
39

La solución se da a continuación,

Desde el caparazón de Docker,

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

Del anfitrión

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

El archivo se copiará directamente en la ubicación donde se encuentra el contenedor en el sistema de archivos.

atravesar
fuente
10
Gran respuesta. En versiones más recientes de Docker, la ruta se ha renombrado a / var / lib / docker / aufs / mnt /
Alex Volkov el
La ruta de Devicemapper no parece funcionar en Fedora con Docker 1.6. Lo puse como una Q separada, stackoverflow.com/questions/29939419/… , cualquier comentario sería apreciado.
Yogesh_D
33

Por lo general, hay tres tipos:

  1. De un contenedor al host

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

dev1

  1. Del host a un contenedor

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

dev2

  1. De un contenedor a un contenedor combina 1 y 2

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

dev3

Ali Hallaji
fuente
66
docker cp funciona en ambos sentidos. No es necesario ejecutar, cat y redirigir. docker cp host_file.txt contenedor: / ruta /
tbm
32

Otra solución para copiar archivos en un contenedor en ejecución es usar tar:

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

Copia el archivo foo.shen /tmpel contenedor.

Editar: Eliminar el redundante -f, gracias al comentario de Maarten .

joemat
fuente
Esto es bueno si necesita enviar un directorio completo. Para un solo archivo, la respuesta de Erik es más simple.
Kelvin
1
@ Kelvin: Pero tar también conserva los atributos y el nombre del archivo. Entre otros, eso significa que solo tiene que escribir el nombre una vez (y allí obtendrá la finalización de la pestaña desde su shell). Entonces diría que tar es realmente más simple, siempre que esté instalado en el contenedor.
Maarten
1
Sin -f -embargo, es un poco redundante, el comportamiento predeterminado es escribir en stdout de todos modos.
Maarten
esto significa que hay una dependencia del host en tar
cellige
Tienes razón: necesitas instalar tar en el host y dentro del contenedor. Hoy en día, usar docker cp es la mejor solución.
joemat
24

Para copiar un archivo del host al contenedor en ejecución

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

Basado en la respuesta de Erik y los comentarios de Mikl y z0r.

Andrea
fuente
Las soluciones aceptadas a veces perturban la sangría de los archivos cuando se transfieren a contenedores en ejecución. Esto funciona perfecto para tales casos
Sueños
15

Esta es una respuesta directa a la pregunta 'Copiar archivos del host al contenedor Docker' planteada en esta pregunta en el título.

Tratar docker cp. Es la forma más fácil de hacerlo y funciona incluso en mi Mac. Uso:

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

Esto copiará el archivo some-file.txten el directorio /rootde su máquina host en el contenedor Docker nombrado some-docker-containeren el directorio /root. Está muy cerca de la sintaxis de copia segura. Y como se muestra en la publicación anterior, puede usarlo al revés. Es decir, también copia los archivos del contenedor al host.

Y antes de que descargues esta publicación, ingresa docker cp --help. Leer la documentación puede ser muy útil, a veces ...

Si no le gusta de esa manera y desea volúmenes de datos en su contenedor ya creado y en ejecución, la recreación es su única opción hoy. Consulte también ¿Cómo puedo agregar un volumen a un contenedor Docker existente? .

Hiro.protagonista
fuente
15

Intenté la mayoría de las soluciones (votadas) aquí, pero en Docker 17.09 (en 2018) ya no hay una carpeta / var / lib / docker / aufs.

Así de simple docker cpresolvió esta tarea.

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

¿Cómo obtener container_name?

 docker ps 

Hay una NAMESseccion. No uses a IMAGE.

Aerin
fuente
12

Para copiar archivos / carpetas entre un contenedor y el sistema de archivos local, escriba el comando:

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

Por ejemplo,

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

Para obtener la identificación del contianer, escriba el comando dado:

docker ps

El contenido anterior está tomado de docker.com .

prayagupd
fuente
8

Suponiendo que el contenedor ya se está ejecutando, escriba el comando dado:

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

Para compartir archivos usando el directorio compartido, ejecute el contenedor escribiendo el comando dado:

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

Nota: Pueden surgir problemas con los permisos ya que los usuarios del contenedor no son los mismos que los usuarios del host.

johndodo
fuente
1
Además:docker exec -it <container_id> bash -c 'cat > /path/to/container/file' < /path/to/host/file/
Mikl
2
Tenga en cuenta que catno se terminará una vez que salga. Si es importante para usted (si está copiando scripts de bash, bash se negará a ejecutarlos), debe ejecutar lsof | grep yourfilenamey eliminar el catproceso que contiene dicho archivo.
johndodo
¡Gracias! Gran consejo ¿Puedes decirme cómo matar este proceso con un comando? Algo así como kill $(lsof | grep /path/to/file | sed ...). Estaré agradecido por tu ayuda
Mikl
kill $(docker top CONTAINERNAME | sed -n '/cat$/p' | sed 's/^root[^0-9]\+\([0-9]\+\).*$/\1/')
Mikl
8

Este es el comando para copiar datos de Docker a Host:

docker cp container_id:file path/filename /hostpath

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

A continuación se muestra el comando para copiar datos del host a la ventana acoplable:

docker cp a.txt ccfbeb35116b:/home/
Maninder
fuente
7

En un entorno acoplable, todos los contenedores se encuentran en el directorio:

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

Para copiar el directorio / archivo fuente a cualquier parte del contenedor, escriba el comando dado:

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

0x3bfc
fuente
5

tary docker cpson una buena combinación para copiar todo en un directorio.

Crear un contenedor de volumen de datos

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

Para preservar la jerarquía de directorios

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

Revisa tu trabajo

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

Si el host es CentOS o Fedora, hay un proxy que NO está en /var/lib/docker/aufs, pero está debajo de /proc:

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

Este cmd copiará todo el contenido del datadirectorio al /contenedor con la identificación "containerid".

Abdennour TOUMI
fuente
Esto no es exclusivo de Redhat: también funciona en Debian. (Tal vez todo Gnu / Linux con /proc). También extienda la ruta para colocar el archivo en otro lugar, no solo en la raíz.
ctrl-alt-delor
5

En caso de que no esté claro para alguien como yo lo que significa mycontaineren la respuesta @ h3nrik, en realidad es la identificación del contenedor. Para copiar un archivo WarpSquare.mp4en /app/example_scenes/1440p60desde un contenedor ventana acoplable salido a la carpeta actual utilicé esta.

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

donde docker ps -q -lmuestra el id del contenedor de la última instancia salida. En caso de que no sea un contenedor salido, puede obtenerlo docker container lsodocker ps

ishandutta2007
fuente
1
Puede enumerar identificadores de contenedores salidos con docker ps -ao docker container ls -a.
0x7d7b
4

Muchos de los que encuentran esta pregunta pueden tener el problema de copiar archivos en una imagen de Docker mientras se está creando (lo hice).

En ese caso, puede usar el COPYcomando Dockerfileque usa para crear la imagen.

Ver la documentación .

Klas Mellbourn
fuente
4

Puede rastrear la dirección IP de su máquina local utilizando

ifconfig

Luego ingrese a su contenedor Docker y escriba

scp user_name@ip_address:/path_to_the_file destination

En cualquier caso, si no tiene un cliente y servidor SSH instalado, simplemente instálelo usando:

sudo apt-get install openssh-server
Harshit Anand
fuente
Muchas gracias, funcionó bien para mí. Además, lo encontré más eficiente que otras formas
user1314742
Esta es una solución horrible en términos de seguridad.
4

Este es un en línea para copiar un solo archivo mientras se ejecuta un contenedor tomcat.

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

Esto copiará el archivo war al directorio webapps y hará que su aplicación se ejecute en poco tiempo.

karthik101
fuente
1
-v se montará (es decir, creará un enlace), no se copiará
Vitaliy Ulantikov
la diferencia en el resultado es que el montaje oculta el contenido del contenedor anterior, por ejemplo, si monta una carpeta de host en una carpeta del contenedor, ya no podrá ver el contenido de la carpeta del contenedor anterior
mrq
4

Sintaxis de Contenedor:

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

En el archivo acoplable

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
fuente
3

La mejor manera de copiar archivos al contenedor que encontré es montar un directorio en el host usando la -vopción del comando docker run.

Prakash Varandani
fuente
3

Hay buenas respuestas, pero muy específicas. Descubrí que docker pses una buena manera de obtener la identificación del contenedor que le interesa. Luego, haga

mount | grep <id>

para ver dónde está montado el volumen. Eso es

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

para mí, pero podría ser una ruta diferente dependiendo del sistema operativo y la configuración. Ahora simplemente copie los archivos a esa ruta.

Usar -vno siempre es práctico.

akostadinov
fuente
3

Acabo de comenzar a usar Docker para compilar VLC, esto es lo que puede hacer para copiar archivos de un lado a otro de los contenedores:

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

¡Busque un archivo familiar en ese txt y tendrá la carpeta, cd como root y listo! copia todo lo que quieras

Puede haber un camino con "fusionado", creo que quieres el que tiene "diff".

Además, si sale del contenedor y desea volver a donde lo dejó:

docker ps -a
docker start -i containerid

Supongo que es útil cuando no nombraste nada con un comando como

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

Claro que el método hacker pero ¿y qué?

colin lamarre
fuente
3
docker cp SRC_PATH CONTAINER_ID:DEST_PATH

Por ejemplo, quiero copiar mi archivo xxxx / download / jenkins a tomcat

Empiezo a obtener la identificación del contenedor 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
fuente
2

Mi metodo favorito

Contenedores

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

o

mv -f file.txt /var/lib/docker/aufs/mnt/$CONTAINER_ID/rootfs/root/file.txt
usuario3159411
fuente
La ruta de Devicemapper no parece funcionar en Fedora con Docker 1.6. Lo puse como una Q separada, stackoverflow.com/questions/29939419/… , cualquier comentario sería apreciado.
Yogesh_D
2

En mi opinión, no tiene que copiar archivos dentro de la imagen, pero puede usar GIT o SVN para sus archivos y luego configurar un volumen sincronizado con una carpeta local. Use un script mientras ejecuta el contenedor que puede verificar si los datos ya existen en la carpeta local, si no los copia del repositorio GIT. Eso hace que tu imagen sea muy ligera.

h.aittamaa
fuente
Esto parece un riesgo de seguridad y una pesadilla de acceso a la espera de suceder. ¿Cómo proporciona acceso al repositorio git desde su imagen? Incluso suponiendo que sea un repositorio público, asumirá que el host en el que se ejecuta su contenedor tiene acceso a ese repositorio.
tbm
Estoy de acuerdo con usted si se usa git dentro del contenedor acoplable. Pero en nuestro caso, el script se ejecuta desde la máquina host
h.aittamaa