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?


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

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.


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

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

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

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

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 .
    

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.


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


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 .


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.


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? .


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.


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 .


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.


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/

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/


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

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".


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


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 .


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

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.


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"

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.


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.


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é?


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/

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

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.


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.