web-dev-qa-db-fra.com

Pourquoi les images de conteneur Docker sont-elles si grandes?

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.

135
Zen

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
93
Andy

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.

49
Travis Reeder

Voici d'autres choses que vous pouvez faire :

  • Évitez les commandes RUN lorsque vous le pouvez. Mettez autant que possible dans une commande RUN (en utilisant &&)
  • nettoie les outils inutiles tels que wget ou git (dont vous avez besoin uniquement pour télécharger ou créer des éléments, mais pas pour exécuter votre processus)

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!

20
Munchkin

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.

18
michau

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:

  1. export du menu fixe [ID conteneur] -o nomdeteneur.tar
  2. importation de menu fixe -m "message commis ici" nomdispositif.tar imagename: tag

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.

13
Jeffrey Schmitz

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
6
tmz83

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.

https://github.com/jwilder/docker-squash

4
jeremyjjbrown

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.

0
99Sono