J'ai fait une image simple via Dockerfile de Fedora (initialement 320 Mo).
Ajout de Nano (ce petit éditeur de 1 Mo de taille) et la taille de l'image est passée à 530 Mo. J'ai ajouté Git en plus de cela (30 Mo), puis ma taille d'image fusées célestes à 830 Mo.
N'est-ce pas insensé?
J'ai essayé d'exporter et d'importer un conteneur pour supprimer l'historique / les images intermédiaires. Cet effort a permis d'économiser jusqu'à 25 Mo, maintenant ma taille d'image est de 804 Mo. J'ai également essayé d'exécuter de nombreuses commandes sur une RUN
, mais j'obtiens toujours le même 830 Mo initial.
Je doute que cela vaille la peine d'utiliser Docker. Je veux dire, j'ai à peine installé quoi que ce soit et je frappe 1 Go de plus. Si je devais ajouter des choses sérieuses comme une base de données et ainsi de suite, je pourrais manquer d'espace disque.
Quelqu'un souffre de la taille ridicule des images? Comment gères-tu cela?
À moins que mon Dockerfile soit horriblement incorrect?
FROM fedora:latest
MAINTAINER Me NotYou <[email protected]>
RUN yum -y install nano
RUN yum -y install git
mais il est difficile d'imaginer ce qui pourrait mal tourner ici.
yum clean all
-il un effet sur la taille?docker images
laquelle dans la dernière colonne indique un 830 Mo de poids. Je ne sais peut-être pas quelle est la taille réelle de mon image car la commande docker images indique que cette taille de 830 Mo est virtuelle. Mais là encore, quelle est la taille réelle de l'image?Réponses:
Comme @rexposadas l'a dit, les images incluent toutes les couches et chaque couche comprend toutes les dépendances pour ce que vous avez installé. Il est également important de noter que les images de base (comme
fedora:latest
ont tendance à être très simples. Vous pourriez être surpris par le nombre de dépendances de votre logiciel installé.J'ai pu réduire considérablement votre installation en ajoutant
yum -y clean all
à chaque ligne:Il est important de le faire pour chaque RUN, avant que la couche ne soit validée, sinon les suppressions ne suppriment pas réellement les données. Autrement dit, dans un système de fichiers union / copie sur écriture, le nettoyage à la fin ne réduit pas vraiment l'utilisation du système de fichiers car les données réelles sont déjà validées dans les couches inférieures. Pour contourner ce problème, vous devez nettoyer chaque couche.
la source
docker images
). Est-il possible de supprimer / supprimer / détruire ces anciennes couches? Pour être plus précis: je voudrais supprimer complètement (en me basant sur votre exemple) les images: 172743bd5d60, 3f2fed40e4b0, fd241224e9cf, 511136ea3c5a de l'historique, de sorte que ma taille d'image virtuelle soit plus ou moins la même que la taille d'image finale, ici ~ 260 Mo .docker export
etdocker import
encore. Cela aplatirait les couches. Je ne pense pas que cela réduirait la taille, mais je peux me tromper.docker ps -s
, la taille réelle du disque dur apparaît, ce qui dans mon cas l'était-1B
. Cela semble raisonnable, moins 1 octet . J'ai gagné de la place sur le disque dur ... cela semble légitime.Les images Docker ne sont pas volumineuses, vous créez simplement de grandes images.
L'
scratch
image est 0B et vous pouvez l'utiliser pour empaqueter votre code si vous pouvez compiler votre code dans un binaire statique. Par exemple, vous pouvez compiler votre programme Go et l' empaqueterscratch
pour créer une image entièrement utilisable de moins de 5 Mo.La clé est de ne pas utiliser les images officielles de Docker, elles sont trop grandes. Scratch n'est pas non plus très pratique, je vous recommande donc d'utiliser Alpine Linux comme image de base. Il fait environ 5 Mo, puis n'ajoutez que ce qui est requis pour votre application. Cet article sur Microcontainers vous montre comment créer de très petites images basées sur Alpine.
MISE À JOUR: les images officielles de Docker sont basées sur l'alpin maintenant, elles sont donc bonnes à utiliser maintenant.
la source
Voici d'autres choses que vous pouvez faire :
RUN
commandes multiples lorsque vous le pouvez. Mettez autant que possible dans une seuleRUN
commande (en utilisant&&
)Avec ces deux ET les recommandations de @Andy et @michau, j'ai pu redimensionner mon image nodejs de 1,062 Go à 542 Mo.
Edit: Une autre chose importante: "Il m'a fallu un certain temps pour vraiment comprendre que chaque commande Dockerfile crée un nouveau conteneur avec les deltas. [...] Peu importe si vous rm -rf les fichiers dans une commande ultérieure; ils continuent d'exister dans un conteneur de couche intermédiaire. " Alors maintenant , je réussi à mettre
apt-get install
,wget
,npm install
(avec dépendances git) etapt-get remove
en une seuleRUN
commande, maintenant mon image a seulement 438 Mo.Modifier 29/06/17
Avec Docker v17.06, il y a de nouvelles fonctionnalités pour Dockerfiles: vous pouvez avoir plusieurs
FROM
instructions dans un Dockerfile et seuls les éléments du dernierFROM
seront dans votre image Docker finale. Ceci est utile pour réduire la taille de l'image, par exemple:Cela donnera une image ayant uniquement l'image de base nodejs plus le contenu de / var / my-project des premières étapes - mais sans ruby, python, git, openssh et gcc!
la source
Oui, ces tailles sont ridicules, et je ne sais vraiment pas pourquoi si peu de gens le remarquent.
J'ai créé une image Ubuntu qui est en fait minimale (contrairement à d'autres images dites "minimales"). Il s'appelle
textlab/ubuntu-essential
et dispose de 60 Mo.L'image ci-dessus fait 82 Mo après l'installation de nano.
Git a beaucoup plus de prérequis, donc l'image s'agrandit, environ 192 Mo. C'est encore moins que la taille initiale de la plupart des images.
Vous pouvez également consulter le script que j'ai écrit pour créer l'image minimale d'Ubuntu pour Docker . Vous pouvez peut-être l'adapter à Fedora, mais je ne sais pas combien vous pourrez désinstaller.
la source
Ce qui suit m'a beaucoup aidé:
Après avoir supprimé les paquets inutilisés (par exemple redis 1200 mb libérés) à l'intérieur de mon conteneur, j'ai fait ce qui suit:
Les couches s'aplatissent. La taille de la nouvelle image sera plus petite car j'ai supprimé les packages du conteneur comme indiqué ci-dessus.
Cela a pris beaucoup de temps pour comprendre cela et c'est pourquoi j'ai ajouté mon commentaire.
la source
docker export <CONTAINER ID> | docker import - some-image-name:latest
Pour une meilleure pratique, vous devez exécuter une seule commande RUN, car chaque instruction RUN du Dockerfile écrit une nouvelle couche dans l'image et chaque couche nécessite de l'espace supplémentaire sur le disque. Afin de réduire au minimum le nombre de couches, toute manipulation de fichier telle que l'installation, le déplacement, l'extraction, la suppression, etc., devrait idéalement être effectuée sous une seule instruction RUN.
la source
Docker Squash est une très bonne solution à cela. vous pouvez
$packagemanager clean
dans la dernière étape au lieu de dans chaque ligne, puis exécutez simplement un docker squash pour vous débarrasser de toutes les couches.https://github.com/jwilder/docker-squash
la source
Oui, le système de couches est assez surprenant. Si vous avez une image de base et que vous l'incrémentez en procédant comme suit:
L'image a exactement la même taille. Cela signifie essentiellement que vous devez réussir à mettre dans vos étapes RUN beaucoup de magie d'extrait, d'installation et de nettoyage pour rendre les images aussi petites que le logiciel installé.
Cela rend la vie beaucoup plus difficile ...
Le dockerBuild n'a pas d'étapes RUN sans validation.
la source