Cómo modificar imágenes de Docker

Supongo que está un poco familiarizado con Docker y conoce conceptos básicos como ejecutar contenedores Docker, etc.

En artículos anteriores, hemos discutido la actualización del contenedor docker y la escritura de archivos docker.

¿Qué es exactamente modificar una imagen acoplable?

Una imagen de contenedor se construye en capas (o es una colección de capas), cada instrucción de Dockerfile crea una capa de la imagen. Para exampleconsidere el siguiente Dockerfile:

                      
                        FROM alpine:latest

RUN apk add --no-cache python3

ENTRYPOINT ["python3", "-c", "print('Hello World')"]

                      
                    

Dado que hay un total de tres comandos de Dockerfile, la imagen creada a partir de este Dockerfile contendrá un total de tres capas.

Puede confirmarlo construyendo la imagen:

                      
                        docker image built -t dummy:0.1 .

                      
                    

Y luego usando el comando docker image history en la imagen construida.

                      
                        articles/Modify a Docker Image on  modify-docker-images [?] took 12s 
❯ docker image history dummy:0.1 
IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
b997f897c2db   10 seconds ago   /bin/sh -c #(nop)  ENTRYPOINT ["python3" "-c…   0B        
ee217b9fe4f7   10 seconds ago   /bin/sh -c apk add --no-cache python3           43.6MB    
28f6e2705743   35 hours ago     /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B        
<missing>      35 hours ago     /bin/sh -c #(nop) ADD file:80bf8bd014071345b…   5.61MB

                      
                    

Ignore la última capa ‘ ‘.

Cada una de estas capas es de solo lectura. Esto es beneficioso porque dado que estas capas son de solo lectura, ningún proceso asociado con una instancia en ejecución de esta imagen podrá modificar el contenido de esta imagen, por lo tanto, estas capas pueden ser compartidas por muchos contenedores sin tener que mantener un copia para cada instancia. Pero para que los procesos de los contenedores puedan realizar r/w, se agrega otra capa encima de las capas de RO existentes cuando se crean los contenedores, esto se puede escribir y no se comparte con otros contenedores.

La desventaja de esta capa r/w es que los cambios realizados en esta capa no son persistentes, aunque puede usar volúmenes para conservar algunos datos, a veces puede necesitar/querer agregar una capa antes de alguna capa existente, o eliminar una capa de un imagen o simplemente reemplazar una capa. Estas son las razones por las que uno podría querer modificar un docker imagen.

En este artículo, cubriré todos los casos que mencioné anteriormente, usando diferentes métodos.

Métodos para modificar una imagen acoplable

Hay dos formas de modificar una imagen acoplable.

  1. A través de Dockerfiles.
  2. Usando el comando docker container commit .

Explicaré ambos métodos y, al final, también agregaré qué caso de uso sería mejor para el método en contexto.

Método 1: modificar la imagen de Docker a través de Dockerfile

Modificar una imagen acoplable esencialmente significa modificar las capas de una imagen. Ahora, dado que cada comando de Dockerfile representa una capa de la imagen, la modificación de cada línea de un Dockerfile también cambiará la imagen respectiva.

Entonces, si tuviera que agregar una capa a la imagen, simplemente puede agregarle otra instrucción Dockerfile, para eliminar una, eliminaría una línea y para cambiar una capa, cambiaría la línea en consecuencia.

Hay dos formas de usar un Dockerfile para modificar una imagen.

  1. Usando la imagen que desea modificar como imagen base y construya una imagen secundaria.
  2. Modificar el Dockerfile real de la imagen que desea cambiar.

Permítanme explicar qué método debe usarse, cuándo y cómo.

1. Usar una imagen como imagen base

Aquí es cuando toma la imagen que desea modificar y le agrega capas para crear una nueva imagen secundaria. A menos que una imagen se construya desde cero, cada imagen es una modificación de la misma imagen base principal.

Considere el Dockerfile anterior. Digamos que la imagen creada a partir de esa imagen se llama dummy:0.1 . Ahora, si tuviera que pensar que ahora necesito usar Perl en lugar de Python3 para imprimir “Hello World”, pero tampoco quiero eliminar Python3, podría usar el dummy:0.1 image como la imagen base (ya que Python3 ya está allí) y construya a partir de eso de la siguiente manera

                      
                        FROM dummy:0.1

RUN apk add --no-cache perl

ENTRYPOINT ["perl", "-e", "print "Hello Worldn""]

                      
                    

Aquí estoy construyendo encima de dummy:0.1 agregando más capas a él como mejor me parezca.

Este método no será de mucha ayuda si su intención es cambiar o eliminar alguna capa existente. Para eso, debes seguir el siguiente método.

2. Modificando el Dockerfile de la imagen

Dado que las capas existentes de una imagen son de solo lectura, no puede modificarlas directamente a través de un nuevo Dockerfile. Con el FROM comando en un Dockerfile, toma una imagen como base y construye en o agregarle capas.

Algunas tareas pueden requerir que alteremos una capa existente, aunque puede hacerlo usando el método anterior con un montón de contradicciones. RUN instrucciones (como eliminar archivos, eliminar/reemplazar paquetes agregados en alguna capa anterior), no es una solución ideal o lo que recomendaría. Porque agrega capas adicionales y aumenta bastante el tamaño de la imagen.

Un mejor método sería no usar la imagen como imagen base, sino cambiar el Dockerfile real de esa imagen. Considere nuevamente el Dockerfile anterior, ¿y si no tuviera que mantener Python3 en esa imagen y reemplazar el paquete Python3 y el comando con los de Perl?

Si hubiera seguido el método anterior, habría tenido que crear un nuevo Dockerfile así:

                      
                        FROM dummy:0.1

RUN apk del python3 && apk add --no-cache perl

ENTRYPOINT ["perl", "-e", "print "Hello Worldn""]

                      
                    

Si se construye, habrá un total de cinco capas en esta imagen.

                      
                        articles/Modify a Docker Image on  modify-docker-images [?] took 3s 
❯ docker image history dummy:0.2
IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
2792036ddc91   10 seconds ago   /bin/sh -c #(nop)  ENTRYPOINT ["perl" "-e" "…   0B        
b1b2ec1cf869   11 seconds ago   /bin/sh -c apk del python3 && apk add --no-c…   34.6MB    
ecb8694b5294   3 hours ago      /bin/sh -c #(nop)  ENTRYPOINT ["python3" "-c…   0B        
8017025d71f9   3 hours ago      /bin/sh -c apk add --no-cache python3 &&    …   43.6MB    
28f6e2705743   38 hours ago     /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B        
<missing>      38 hours ago     /bin/sh -c #(nop) ADD file:80bf8bd014071345b…   5.61MB

                      
                    

Además, el tamaño de la imagen es de 83,8 MB.

                      
                        articles/Modify a Docker Image on  modify-docker-images [?] 
❯ docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
dummy        0.2       2792036ddc91   19 seconds ago   83.8MB

                      
                    

Ahora, en lugar de hacer eso, tome el Dockerfile inicial y cambie los de Python3 a Perl así

                      
                        FROM alpine:latest

RUN apk add --no-cache perl

ENTRYPOINT ["perl", "-e", "print "Hello Worldn""]

                      
                    

El número de capas se ha reducido a 3 y el tamaño ahora es de 40,2 MB.

                      
                        articles/Modify a Docker Image on  modify-docker-images [?] took 3s 
❯ docker image history dummy:0.3
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
f35cd94c92bd   9 seconds ago   /bin/sh -c #(nop)  ENTRYPOINT ["perl" "-e" "…   0B        
053a6a6ba221   9 seconds ago   /bin/sh -c apk add --no-cache perl              34.6MB    
28f6e2705743   38 hours ago    /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B        
<missing>      38 hours ago    /bin/sh -c #(nop) ADD file:80bf8bd014071345b…   5.61MB    

articles/Modify a Docker Image on  modify-docker-images [?] 
❯ docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
dummy        0.3       f35cd94c92bd   29 seconds ago   40.2MB

                      
                    

Imagen cambiada con éxito.

El método anterior es más útil cuando solo va a agregar capas encima de las existentes, pero no es muy útil cuando intenta modificar las capas existentes, como eliminar una, reemplazar una, reordenar las existentes, etc. Ahí es donde brilla este método.

Método 2: Modificar la imagen usando docker commit

Existe otro método en el que puede tomar una instantánea de un contenedor en ejecución y convertirlo en una imagen propia.

Construyamos un dummy:0.1 imagen idéntica, pero esta vez sin usar un Dockerfile. Desde que usé alpine:latest como dummy:0.1 base de , haz girar un contenedor de esa imagen.

                      
                        docker run --rm --name alpine -ti alpine ash

                      
                    

Ahora dentro del contenedor, agregue el paquete Python3, apk add --no-cache python3 . Una vez hecho esto, abra una nueva ventana de terminal y ejecute el siguiente comando (o algo similar)

                      
                        docker container commit --change="ENTRYPOINT ["python3", "-c", "print("Hello World")"]" alpine dummy:0.4

                      
                    

Con el --change flag Estoy agregando una instrucción Dockerfile al nuevo dummy:04 imagen (en este caso, la ENTRYPOINT instrucción).

Con el docker container commit Básicamente, convierte la capa r/w más externa en una capa ar/o, la agrega a las capas de la imagen existente y crea una nueva imagen. Este método es más intuitivo/interactivo, por lo que es posible que desee usarlo en lugar de Dockerfiles, pero comprenda que esto no es muy reproducible. También se aplican las mismas reglas para eliminar o alterar cualquier capa existente, agregar una capa solo para eliminar algo o modificar algo hecho en una capa anterior no es la mejor idea, al menos en la mayoría de los casos.

Eso concluye este artículo. Espero que esto haya sido útil para usted, si tiene alguna pregunta, comente a continuación.

Related Posts