¿Extraer archivo de la imagen del acoplador?

24

Me gustaría extraer un archivo de una imagen de Docker sin tener que ejecutar la imagen.

La docker saveopción no es actualmente una opción viable para mí, ya que está guardando un archivo demasiado grande solo para liberar un archivo específico.

BlakBat
fuente
¿Qué distro está usando?
ryekayo
@ryekayo: Ubuntu 14, docker 1.12.4 (api 1.24)
BlakBat

Respuestas:

21

Puede extraer archivos de una imagen con los siguientes comandos:

docker create $image  # returns container ID
docker cp $container_id:$source_path $destination_path
docker rm $container_id

Según la docker create documentación , esto no ejecuta el contenedor:

El docker createcomando crea una capa de contenedor grabable sobre la imagen especificada y la prepara para ejecutar el comando especificado. La identificación del contenedor se imprime en STDOUT. Esto es similar a docker run -dexcepto que el contenedor nunca se inicia. Luego puede usar el docker start <container_id>comando para iniciar el contenedor en cualquier momento.


Como referencia (mi respuesta anterior), una forma menos eficiente de extraer un archivo de una imagen es la siguiente:

docker run some_image cat $file_path > $output_path
bbc
fuente
3
Es posible que desee anular el punto de entrada. docker run --entrypoint /bin/sh my_image -c /bin/cat some_file
Andrew
1
Esto ejecuta la imagen, que es específicamente lo que no quería hacer como se indica en mi pregunta.
BlakBat
Ah, ese es un buen punto. Estoy de acuerdo en que mi respuesta actual no es satisfactoria entonces.
bbc
1
@BlakBat ¿Esta respuesta actualizada funciona para usted? Supongo que debería haber creado una nueva respuesta, pero ya está lista.
bbc
1
@bbc Esta respuesta actualizada, de hecho, no inicia un contenedor (el meollo de la pregunta), y no requiere ser root.
BlakBat
2

Nada de lo anterior funcionó para mí. El comando de trabajo completo es:

docker run --rm --entrypoint /bin/sh image_name -c "cat /path/filename" > output_filename

Sin comillas catse pasa sin nombre de archivo, por lo que no sabe qué mostrar. También es una buena idea eliminar el contenedor una vez finalizado el comando.

sekrett
fuente
El comando al que te refieres solo funcionará dependiendo de la ventana acoplable y de cuán correctamente se configuró ENTRYPOINT / CMD en el Dockerfile; Esto no tiene nada que ver con las citas. También dice que elimine el contenedor, pero especifica --rm. Por último, cuando publiqué mi pregunta, especifiqué "sin tener que ejecutar la imagen" y ninguna respuesta fue una solución teniendo esto en cuenta.
BlakBat
1
Independientemente de qué CMD y ENTRYPOINT se configuraron en Dockerfile, anulo ambos, por lo que funcionaría siempre (en Linux, por supuesto). ¿Qué quieres decir con "dependiendo del acoplador"? Configuración, versión, env, ¿qué? Su pregunta no es correcta porque las imágenes no se pueden ejecutar, solo los contenedores sí. Creo que no hay una respuesta correcta, tienes que lidiar con muchos archivos o crear un contenedor temporal. --rm elimina el contenedor temporal, las respuestas de otros dejan algo de basura en su disco.
sekrett
1

Si no me equivoco, creo que los contenedores docker almacenan archivos en caché creados en el siguiente directorio para Ubuntu:

/var/lib/docker/aufs/diff/<container_id>

Desde allí, debería poder acceder al sistema de archivos y recuperar sus archivos.

ryekayo
fuente
No Ese directorio solo contiene layersizey json, y tampoco es legible por el usuario (incluso si el usuario está en el grupo acoplable). /var/lib/docker/aufs/diffcontendrá el archivo que busco (pero no está clasificado por la identificación del contenedor) y tampoco es legible.
BlakBat
Dame algunos y lo buscaré. Sé a ciencia cierta que hay una manera de recuperar los archivos sin ingresar al contenedor o ejecutarlo.
ryekayo
Por no legible, ¿cómo se muestra? He encontrado un ejemplo en el que puede extraer archivos de texto de los contenedores yendo al directorio / var / lib / docker / aufs / diff / *
ryekayo
Mi error. El usuario puede acceder /var/lib/docker/aufs(pero no todos los demás directorios /var/lib/docker/)
BlakBat
¿Se puede acceder como root?
ryekayo
0

Si almacenar la salida completa de docker saveno es una opción, puede usar tuberías para extraer solo el archivo necesario.

Desafortunadamente, debido a que el resultado es un "alquitrán de alquitranes", puede ser un proceso ligeramente iterativo.

Lo que hice cuando necesitaba extraer un archivo en este momento fue:

1) Determine qué versión de la imagen cambió el archivo que le interesa más recientemente (cómo lo hace probablemente depende de su imagen) y la fecha en que se creó / guardó

2) Obtenga la tabla de contenido completa de la salida del docker savecomando con:

docker save IMAGE_NAME | tar -tvf -

3) Ajuste los layer.tararchivos en la salida de ese comando que coincidan con la fecha de la imagen que determinó en el paso 1. (puede agregar | grep layer.tarpara mostrar esos archivos)

4) Extraiga el layer.tararchivo al estándar y obtenga la tabla de contenido:

docker save IMAGE_NAME | tar -xf - -O CHECKSUM_FROM_LIST/layer.tar | tar -tvf -

5) Verifique que el archivo que desea esté en la lista y extráigalo una vez que encuentre el nombre:

docker save IMAGE_NAME | tar -xf - -O CHECKSUM_FROM_LIST/layer.tar | tar -xf - PATH/TO/YOUR/FILE

Si hay más de un layer.tararchivo que coincida con la fecha que busca en el paso 2/3, es posible que deba repetir el paso 4 para cada uno de ellos hasta encontrar el correcto

Reemplace el texto en mayúsculas en los comandos anteriores con los nombres de imagen, sumas de verificación y nombres de archivo correctos para su caso.

Michael Firth
fuente