J'ai créé une image simple via Dockerfile à partir de Fedora (initialement 320 Mo).
Ajout de Nano (ce petit éditeur de 1 Mo), et la taille de l'image est passée à 530 Mo. J'ai ajouté Git en plus de cela (30 Mo), puis mon image grandit à 830 Mo.
N'est-ce pas fou?
J'ai essayé d'exporter et d'importer des conteneurs pour supprimer l'historique/les images intermédiaires. Cet effort a permis d'économiser jusqu'à 25 Mo. Désormais, la taille de mon image est de 804 Mo. J'ai également essayé d'exécuter plusieurs commandes sur une RUN
, mais j'obtiens toujours le même 830 Mo initial.
J'ai des doutes sur le fait d'utiliser Docker. Je veux dire, j'ai à peine installé quoi que ce soit et je frappe 1 Go sur. Si je dois ajouter des éléments sérieux, comme une base de données, etc., je risque de manquer d’espace disque.
Quelqu'un souffre d'une taille d'images ridicule? Comment gères-tu cela?
Sauf si mon fichier Docker est 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.
Comme @rexposadas l'a dit, les images incluent toutes les couches et chaque couche comprend toutes les dépendances de ce que vous avez installé. Il est également important de noter que les images de base (telles que 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:
FROM Fedora:latest
RUN yum -y install nano && yum -y clean all
RUN yum -y install git && yum -y clean all
Il est important de le faire pour chaque exécution, avant que la couche soit validée, sinon les suppressions ne suppriment pas réellement les données. En d'autres termes, dans un système de fichiers union/copie sur écriture, le nettoyage final ne réduit pas réellement l'utilisation du système de fichiers car les données réelles sont déjà validées pour les couches inférieures. Pour résoudre ce problème, vous devez nettoyer chaque couche.
$ docker history bf5260c6651d
IMAGE CREATED CREATED BY SIZE
bf5260c6651d 4 days ago /bin/sh -c yum -y install git; yum -y clean a 260.7 MB
172743bd5d60 4 days ago /bin/sh -c yum -y install nano; yum -y clean 12.39 MB
3f2fed40e4b0 2 weeks ago /bin/sh -c #(nop) ADD file:cee1a4fcfcd00d18da 372.7 MB
fd241224e9cf 2 weeks ago /bin/sh -c #(nop) MAINTAINER Lokesh Mandvekar 0 B
511136ea3c5a 12 months ago 0 B
Les images Docker ne sont pas grandes, vous construisez simplement de grandes images.
L'image scratch
est 0B et vous pouvez l'utiliser pour mettre votre code en package si vous pouvez le compiler en binaire statique. Par exemple, vous pouvez compiler votre programme Go et le conditionner sur scratch
pour créer une image pleinement 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 très pratique non plus, je vous recommande donc d’utiliser Alpine Linux comme image de base. C'est ~ 5Mo, alors ajoutez seulement ce qui est requis pour votre application. Cet article à propos de Microcontainers vous montre comment construire de très petites images à partir d'Alpine.
MISE À JOUR: les images officielles de Docker sont basées sur Alpine maintenant, donc elles sont bonnes à utiliser maintenant.
Voici d'autres choses que vous pouvez faire :
RUN
lorsque vous le pouvez. Mettez autant que possible dans une commande RUN
(en utilisant &&
)Avec ces deux et les recommandations de @Andy et @michau, j'ai été en mesure de redimensionner mon image nodejs de 1,062 Go à 542 Mo.
Edit: Encore une chose importante: "Il m'a fallu un certain temps pour comprendre que chaque commande Dockerfile crée un nouveau conteneur avec les deltas. [...] Cela n'a pas d'importance si vous rm - rf les fichiers dans une commande ultérieure; ils continuent d'exister dans un conteneur de couche intermédiaire. " Alors, j’ai réussi à insérer apt-get install
, wget
, npm install
(avec dépendances git) et apt-get remove
dans une seule commande RUN
, de sorte que mon image ne dispose que de 438 Mo.
Edit 29/06/17
Docker v17.06 apporte de nouvelles fonctionnalités à Dockerfiles: Vous pouvez avoir plusieurs instructions FROM
dans un fichier Dockerfile et seuls les éléments de la dernière FROM
seront dans votre dernière image Docker. Ceci est utile pour réduire la taille de l'image, par exemple:
FROM nodejs as builder
WORKDIR /var/my-project
RUN apt-get install Ruby python git openssh gcc && \
git clone my-project . && \
npm install
FROM nodejs
COPY --from=builder /var/my-project /var/my-project
Cela se traduira par une image contenant uniquement l'image de base de nodejs et le contenu de/var/my-project dès les premières étapes - mais sans Ruby, python, git, openssh et gcc!
Oui, ces tailles sont ridicules et je ne comprends vraiment pas pourquoi si peu de gens le remarquent.
J'ai créé une image Ubuntu minimale (contrairement à d'autres images dites "minimales"). Il s’appelle textlab/ubuntu-essential
et a 60 Mo.
FROM textlab/ubuntu-essential
RUN apt-get update && apt-get -y install nano
L'image ci-dessus est de 82 Mo après l'installation de nano.
FROM textlab/ubuntu-essential
RUN apt-get update && apt-get -y install nano git
Git a beaucoup plus de prérequis, donc l'image devient plus grande, 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 de temps vous pourrez désinstaller.
Ce qui suit m'a beaucoup aidé:
Après avoir supprimé les packages inutilisés (par exemple, redis libéré à 1 200 Mo) dans mon conteneur, j'ai effectué les opérations suivantes:
Les couches deviennent aplaties. La taille de la nouvelle image sera plus petite car j'ai retiré les paquets du conteneur, comme indiqué ci-dessus.
Cela a pris beaucoup de temps pour comprendre cela et c'est pourquoi j'ai ajouté mon commentaire.
Pour une meilleure pratique, vous devez exécuter une seule commande RUN, car Chaque instruction RUN du fichier Docker écrit un nouveau calque dans l'image et chaque calque nécessite un 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.
FROM Fedora:latest
RUN yum -y install nano git && yum -y clean all
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 un docker squash pour éliminer toutes les couches.
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:
# Test
#
# VERSION 1
# use the centos base image provided by dotCloud
FROM centos7/wildfly
MAINTAINER JohnDo
# Build it with: docker build -t "centos7/test" test/
# Change user into root
USER root
# Extract weblogic
RUN rm -rf /tmp/* \
&& rm -rf /wildfly/*
L'image a exactement la même taille. Cela signifie essentiellement que vous devez réussir à mettre dans vos étapes RUN de nombreuses opérations d'extraction, d'installation et de nettoyage pour rendre les images aussi petites que le logiciel installé.
Cela rend la vie beaucoup plus difficile ...
Il manque des étapes RUN dans dockerBuild sans validation.