GNU/Linux >> Tutoriels Linux >  >> Panels >> Docker

Comment modifier les images Docker

Je suppose que vous êtes un peu familier avec Docker et que vous connaissez les bases comme l'exécution de conteneurs Docker, etc.

Dans les articles précédents, nous avons discuté de la mise à jour du conteneur Docker et de l'écriture de fichiers Docker.

Qu'est-ce exactement que la modification d'une image Docker ?

Une image de conteneur est construite en couches (ou c'est une collection de couches), chaque instruction Dockerfile crée une couche de l'image. Par exemple, considérez le Dockerfile suivant :

FROM alpine:latest

RUN apk add --no-cache python3

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

Puisqu'il y a un total de trois commandes Dockerfile, l'image construite à partir de ce Dockerfile contiendra un total de trois couches.

Vous pouvez le confirmer en créant l'image :

docker image built -t dummy:0.1 .

Et puis en utilisant la commande docker image history sur l'image construite.

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

Ignorer le dernier calque ''.

Chacune de ces couches est en lecture seule. Ceci est avantageux car ces couches étant en lecture seule, aucun processus associé à une instance en cours d'exécution de cette image ne pourra modifier le contenu de cette image. Par conséquent, ces couches peuvent être partagées par de nombreux conteneurs sans avoir à conserver un copie pour chaque instance. Mais pour que les processus des conteneurs puissent effectuer r/w, une autre couche est ajoutée au-dessus des couches RO existantes lors de la création des conteneurs, celle-ci est accessible en écriture et non partagée par d'autres conteneurs.

L'inconvénient de cette couche r/w est que les modifications apportées à cette couche ne sont pas persistantes, bien que vous puissiez utiliser des volumes pour conserver certaines données, parfois vous pouvez avoir besoin/vouloir ajouter une couche avant une couche existante, ou supprimer une couche d'un image ou simplement remplacer un calque. Ce sont les raisons pour lesquelles on peut vouloir modifier un docker existant photo.

Dans cet article, je vais couvrir tous les cas que j'ai mentionnés ci-dessus, en utilisant différentes méthodes.

Méthodes de modification d'une image docker

Il existe deux manières de modifier une image Docker.

  1. Par le biais de Dockerfiles.
  2. Utilisation de la commande docker container commit .

J'expliquerai les deux méthodes, et à la fin, j'ajouterai également quel cas d'utilisation serait le meilleur pour la méthode en contexte.

Méthode 1 :Modification de l'image Docker via Dockerfile

Modifier une image docker signifie essentiellement modifier les calques d'une image. Désormais, puisque chaque commande Dockerfile représente une couche de l'image, la modification de chaque ligne d'un Dockerfile modifiera également l'image respective.

Donc, si vous deviez ajouter un calque à l'image, vous pouvez simplement y ajouter une autre instruction Dockerfile, pour en supprimer un, vous supprimeriez une ligne et pour changer un calque, vous modifieriez la ligne en conséquence.

Il existe deux manières d'utiliser un Dockerfile pour modifier une image.

  1. Utiliser l'image que vous souhaitez modifier comme image de base et créer une image enfant.
  2. Modifier le fichier Dockerfile réel de l'image que vous souhaitez modifier.

Laissez-moi vous expliquer quelle méthode doit être utilisée, quand et comment.

1. Utiliser une image comme image de base

C'est à ce moment que vous prenez l'image que vous souhaitez modifier et que vous y ajoutez des calques pour créer une nouvelle image enfant. À moins qu'une image ne soit créée à partir de zéro, chaque image est une modification de la même image de base parente.

Considérez le Dockerfile précédent. Supposons que l'image créée à partir de cette image s'appelle dummy:0.1 . Maintenant, si je devais penser que je dois maintenant utiliser Perl au lieu de Python3 pour imprimer "Hello World", mais je ne veux pas non plus supprimer Python3, je pourrais simplement utiliser le dummy:0.1 image comme image de base (puisque Python3 est déjà là) et construire à partir de celle-ci comme suit

FROM dummy:0.1

RUN apk add --no-cache perl

ENTRYPOINT ["perl", "-e", "print \"Hello World\n\""]

Ici, je construis au-dessus de dummy:0.1 , en y ajoutant plus de couches comme bon me semble.

Cette méthode ne sera pas très utile si votre intention est de modifier ou de supprimer un calque existant. Pour cela, vous devez suivre la méthode suivante.

2. Modification du Dockerfile de l'image

Étant donné que les calques existants d'une image sont en lecture seule, vous ne pouvez pas les modifier directement via un nouveau Dockerfile. Avec le FROM commande dans un Dockerfile, vous prenez une image comme base et construisez sur ou ajoutez-y des calques.

Certaines tâches peuvent nous obliger à modifier une couche existante, bien que vous puissiez le faire en utilisant la méthode précédente avec un tas de RUN contradictoires instructions (comme la suppression de fichiers, la suppression/le remplacement de packages ajoutés dans une couche précédente), ce n'est pas une solution idéale ou ce que je recommanderais. Parce qu'il ajoute des calques supplémentaires et augmente considérablement la taille de l'image.

Une meilleure méthode serait de ne pas utiliser l'image comme image de base, mais de modifier le Dockerfile réel de cette image. Considérez à nouveau le Dockerfile précédent, et si je n'avais pas à conserver Python3 dans cette image, et à remplacer le package Python3 et la commande par ceux de Perl ?

Si j'avais suivi la méthode précédente, j'aurais dû créer un nouveau Dockerfile comme ça -

FROM dummy:0.1

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

ENTRYPOINT ["perl", "-e", "print \"Hello World\n\""]

Si elle est construite, il y aura un total de cinq couches dans cette image.

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

De plus, la taille de l'image est de 83,8 Mo.

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

Maintenant, au lieu de faire cela, prenez le Dockerfile initial et changez ceux de Python3 en Perl comme ceci

FROM alpine:latest

RUN apk add --no-cache perl

ENTRYPOINT ["perl", "-e", "print \"Hello World\n\""]

Le nombre de calques a été réduit à 3 et la taille est désormais de 40,2 Mo.

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

Image modifiée avec succès.

La méthode précédente est plus utile lorsque vous allez simplement ajouter des calques au-dessus de ceux existants, mais n'est pas très utile lorsque vous essayez de modifier les calques existants comme en supprimer un, en remplacer un, réorganiser les existants et bientôt. C'est là que cette méthode brille.

Méthode 2 :Modification d'une image à l'aide de docker commit

Il existe une autre méthode qui vous permet de prendre un instantané d'un conteneur en cours d'exécution et de le transformer en une image à part entière.

Construisons un dummy:0.1 image identique, mais cette fois sans utiliser de Dockerfile. Depuis que j'utilise alpine:latest comme dummy:0.1 de base, faites tourner un conteneur de cette image.

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

Maintenant, dans le conteneur, ajoutez le package Python3, apk add --no-cache python3 . Une fois cela fait, ouvrez une nouvelle fenêtre de terminal et exécutez la commande suivante (ou quelque chose de similaire)

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

Avec le --change flag J'ajoute une instruction Dockerfile au nouveau dummy:04 image (dans ce cas, le ENTRYPOINT instructions).

Avec le docker container commit commande, vous convertissez essentiellement le calque r/w le plus externe en calque r/o, ajoutez-le aux calques de l'image existante et créez une nouvelle image. Cette méthode est plus intuitive/interactive, vous pouvez donc l'utiliser à la place de Dockerfiles, mais comprenez que ce n'est pas très reproductible. De plus, les mêmes règles s'appliquent à la suppression ou à la modification de tous les calques existants, ajouter un calque juste pour supprimer quelque chose ou modifier quelque chose fait dans un calque précédent n'est pas la meilleure idée, du moins dans la plupart des cas.

Cela conclut cet article. J'espère que celui-ci vous a été utile, si vous avez des questions, n'hésitez pas à commenter ci-dessous.


Docker
  1. Comment déplacer des images Docker entre les hôtes

  2. Comment réduire la taille de l'image Docker :6 méthodes d'optimisation

  3. Comment utiliser un Dockerfile pour créer une image Docker

  4. Comment empaqueter et transférer des images Docker d'un serveur à un autre

  5. Comment valider les modifications apportées à une image Docker

Comment mettre à jour les images Docker vers la dernière version

Comment utiliser Docker Commit pour modifier les images de conteneur

Guide complet pour supprimer les images Docker

Comment créer une image Docker personnalisée avec Dockerfile

Partage d'images Docker sur Docker Hub

Comment répertorier / rechercher / extraire des images docker sous Linux