Cómo crear un Dockerfile a partir de una imagen existente
Las imágenes de Docker se crean mediante la creación de Dockerfiles. El proceso de compilación ejecuta las instrucciones del Dockerfile para crear las capas del sistema de archivos que forman la imagen final.
¿Qué pasa si ya tienes una imagen? ¿Puedes recuperar el Dockerfile desde el que se creó? En este artículo, veremos dos métodos que pueden lograr esto.
El objetivo
Cuando crea sus propias imágenes de Docker, debe almacenar sus Dockerfiles como archivos controlados por versión en su repositorio de origen. Esta práctica garantiza que siempre pueda recuperar las instrucciones utilizadas para ensamblar sus imágenes.
Sin embargo, a veces no tendrá acceso a un Dockerfile. Tal vez esté usando una imagen que está en un registro público pero tiene un repositorio fuente inaccesible. O podría estar trabajando con instantáneas de imágenes que no se corresponden directamente con un Dockerfile versionado. En estos casos, necesita una técnica que pueda crear un Dockerfile a partir de una imagen en su máquina.
Docker no ofrece ninguna funcionalidad integrada para lograr esto. Las imágenes compiladas carecen de una asociación con el Dockerfile desde el que se crearon. Sin embargo, puede aplicar ingeniería inversa al proceso de compilación para producir una buena aproximación del Dockerfile de una imagen bajo demanda.
El comando de historial de Docker
los docker history
El comando revela el historial de capas de una imagen. Muestra el comando utilizado para construir cada capa sucesiva del sistema de archivos, lo que lo convierte en un buen punto de partida al reproducir un Dockerfile.
Aquí hay un Dockerfile simple para una aplicación Node.js:
FROM node:16 COPY app.js . RUN app.js --init CMD ["app.js"]
Construye la imagen usando docker build
:
$ docker build -t node-app:latest .
Ahora inspeccione el historial de capas de la imagen con docker history
:
$ docker history node-app: última IMAGEN CREADA POR TAMAÑO COMENTARIO c06fc21a8eed Hace 8 segundos / bin / sh -c # (nop) CMD ["app.js"] 0B 74d58e07103b Hace 8 segundos / bin / sh -c ./app.js --init 0B 22ea63ef9389 Hace 19 segundos / bin / sh -c # (nop) COPIAR archivo: 0c0828d0765af4dd ... 50B 424bc28f998d Hace 4 días / bin / sh -c # (nop) CMD ["node"] 0BHace 4 días / bin / sh -c # (nop) PUNTO DE ENTRADA ["docker-entry... 0B ...
The history includes the complete list of layers in the image, including those inherited from the node:16
base image. Layers are ordered so the most recent one is first. You can spot where the layers created by the sample Dockerfile begin based on the creation time. These show Docker’s internal representation of the COPY
and CMD
instructions used in the Dockerfile.
The docker history
output is more useful when the table’s limited to just showing each layer’s command. You can disable truncation too to view the full command associated with each layer:
$ docker history node-app:latest --format "{{.CreatedBy}}" --no-trunc /bin/sh -c #(nop) CMD ["app.js"] / bin / sh -c ./app.js --init / bin / sh -c # (nop) COPIAR archivo: 0c0828d0765af4dd87b893f355e5dff77d6932d452f5681dfb98fd9cf05e8eb1 en. / bin / sh -c # (nop) CMD ["node"] / bin / sh -c # (nop) PUNTO DE ENTRADA ["docker-entrypoint.sh"] ...
A partir de esta lista de comandos, puede obtener una descripción general de los pasos realizados para ensamblar la imagen. Para imágenes simples como esta, esta puede ser información suficiente para reproducir con precisión un Dockerfile.
Automatización de la extracción de capas con Whaler y Dfimage
Copiar comandos de docker history
es un proceso laborioso. También es necesario quitar el /bin/sh -c
al comienzo de cada línea, ya que Docker manejó cada instrucción como un comentario de Bash sin operaciones.
Afortunadamente, hay herramientas comunitarias disponibles que pueden automatizar la creación de Dockerfile a partir del historial de capas de una imagen. A los efectos de este artículo, nos centraremos en Whaler, que se incluye en el alpine/dfimage
(Dockerfile-from-Image) Imagen de Docker de la organización Alpine.
ejecutando el dfimage
image y proporcionar una etiqueta Docker generará un Dockerfile que se puede usar para reproducir la imagen a la que se hace referencia. Debe enlazar el socket Docker de su host en el dfimage
contenedor para que pueda acceder a su lista de imágenes y extraer la etiqueta si es necesario.
$ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock alpine/dfimage node-app:latest Analyzing node-app:latest Docker Version: 20.10.13 GraphDriver: overlay2 Environment Variables |PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin |NODE_VERSION=16.14.2 |YARN_VERSION=1.22.18 Image user |User is root Dockerfile: ... ENTRYPOINT ["docker-entrypoint.sh"] CMD ["node"] COPY file:bcbc3d5784a8f1017653685866d30e230cae61d0da13dae32525b784383ac75f in . app.js RUN ./app.js --init CMD ["app.js"]
El Dockerfile creado contiene todo lo que necesita para ir desde scratch
(un sistema de archivos vacío) a la capa final de la imagen especificada. Incluye todas las capas que provienen de la imagen base. Puedes verlos en la primera ENTRYPOINT
y CMD
instrucciones en la salida de muestra anterior (las otras capas de imagen base se han omitido por motivos de brevedad).
Con la excepción de COPY
, las instrucciones específicas de nuestra imagen coinciden con lo que estaba escrito en el Dockerfile original. Ahora puede copiar estas instrucciones en un nuevo Dockerfile
ya sea utilizando la totalidad dfimage
salida o tomando sólo la parte que pertenece a la imagen final. La última opción es solo una posibilidad si conoce la identidad de la imagen base original para que pueda agregar una FROM
instrucciones en la parte superior del archivo.
Las limitaciones
En muchos casos dfimage
podrá ensamblar un Dockerfile utilizable. No obstante, no es perfecto y no se garantiza una coincidencia exacta. El alcance de las discrepancias en comparación con el Dockerfile original de la imagen variará según las instrucciones que se usaron.
No todas las instrucciones se capturan en el historial de capas. Los que no sean compatibles se perderán y no hay forma de que puedas determinar cuáles eran. La mejor precisión se obtiene con instrucciones de comando y metadatos como RUN
, ENV
, WORKDIR
, ENTRYPOINT
y CMD
. RUN
aún podrían faltar instrucciones si su comando no dio como resultado cambios en el sistema de archivos, lo que significa que no se creó una nueva capa de imagen.
COPY
y ADD
Las instrucciones presentan desafíos únicos. El historial no contiene la ruta del archivo de host que se copió en el contenedor. Puede ver que se produjo una copia, pero la ruta de origen hace referencia al hash del archivo que se copió en la imagen desde el contexto de compilación.
A medida que obtenga el destino final, esto puede ser suficiente para ayudarlo a determinar qué se ha copiado y por qué. Luego puede usar esta información para interpolar una nueva ruta de origen en el Dockerfile que puede usar para compilaciones futuras. En otros casos, inspeccionar el archivo dentro de la imagen puede ayudar a revelar el propósito de la copia para que pueda determinar un nombre de archivo significativo para la ruta del host.
Resumen
Las imágenes de Docker no incluyen una forma directa de volver al Dockerfile desde el que se crearon. Sin embargo, todavía es posible reconstruir el proceso de construcción. Para imágenes simples con pocas instrucciones, a menudo puede resolver las instrucciones manualmente mirando el CREATED BY
columna en el docker history
salida del comando.
Las imágenes más grandes con procesos de construcción más complejos se analizan mejor con herramientas como dfimage
. Esto hace el trabajo duro de analizar el detallado docker history
salida para usted, produciendo un nuevo Dockerfile que es una mejor coincidencia para el original probable.
Los esfuerzos de ingeniería inversa no son perfectos y algunas instrucciones de Dockerfile se pierden o alteran durante el proceso de compilación. En consecuencia, no debe asumir que los Dockerfiles creados de esta manera son una representación precisa del original. Puede que tenga que hacer algunos ajustes manuales para ADD
y COPY
instrucciones también, resucitando rutas de archivos de host que se convirtieron para crear referencias de contexto.
Descubre más contenido