Il existe une variété de techniques impliquées, sans solution unique. Vous souhaiterez probablement effectuer plusieurs des opérations suivantes:
Tout d'abord, optimisez vos calques d'images pour les réutiliser. Mettez les étapes fréquemment modifiées plus tard dans le Dockerfile pour augmenter les chances que les premières couches soient mises en cache à partir des versions précédentes. Une couche réutilisée apparaîtra comme plus d'espace disque dans un docker image ls
, mais si vous examinez le système de fichiers sous-jacent, une seule copie de chaque couche est jamais stockée sur le disque. Cela signifie que 3 images de 2 Go chacune, mais qui n'ont que 50 Mo différents dans les dernières couches de la construction, ne prendront que 2,1 Go d'espace disque, même si la liste donne à penser qu'elles utilisent 6 Go puisque vous êtes double comptage de chacune des couches réutilisées.
La réutilisation des couches est la raison pour laquelle vous voyez des images avec des dépendances de construction qui changent rarement, installez-les d'abord avant de les copier dans le code. Voir tout exemple de python qui a un modèle comme:
FROM python
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
# note how the code is copied only after the pip install
# since code changes but requirements.txt doesn't
COPY . .
CMD ["gunicorn", "app:app"]
Choisissez une image de base minimale. Voilà pourquoi vous voyez des gens vont de ubuntu
la debian:slim
(les variantes minces sont plus petites, avec moins d' outils d' expédition), ou même alpine
. Cela réduit la taille de votre point de départ et est très utile si vous extrayez constamment de nouvelles versions de l'image de base. Cependant, si votre image de base change rarement, la réutilisation des calques supprime une grande partie de l'avantage d'une image de base minimale.
La plus petite image de base que vous pouvez choisir est scratch
, qui n'est rien, pas de shell ou de bibliothèques, et n'est utile qu'avec les binaires compilés statiquement. Sinon, choisissez une image de base qui comprend les outils dont vous avez besoin sans beaucoup d'outils dont vous n'avez pas besoin.
Ensuite, toute étape qui modifie ou supprime un fichier doit être combinée avec les étapes précédentes qui créent ce fichier. Sinon, le système de fichiers en couches, qui utilise la copie sur écriture même sur des choses comme un changement d'autorisation de fichier, aura le fichier d'origine dans un calque précédent et la taille de l'image ne diminuera pas lorsque vous supprimez des fichiers. C'est pourquoi vos rm
commandes n'ont aucun effet sur l'espace disque résultant. Au lieu de cela, vous pouvez enchaîner les commandes, comme:
RUN apt-get update \
&& apt-get install -y \
a-package \
wget \
&& ... \
&& apt-get purge -y wget \
&& rm -r a-build-dir \
&& apt-get purge -y a-package
Notez que la surutilisation du chaînage de commandes peut ralentir vos builds car vous devez réinstaller le même ensemble d'outils à chaque fois qu'une condition préalable change (par exemple, le code extrait avec wget). Voir plusieurs étapes ci-dessous pour une meilleure alternative.
Tout fichier que vous créez dont vous n'avez pas besoin dans votre image résultante doit être supprimé, à l'étape qui le crée. Cela inclut les caches de packages, les journaux, les pages de manuel, etc. Pour découvrir quels fichiers sont créés dans chaque couche, vous pouvez utiliser un outil comme wagoodman / dive (que je n'ai pas personnellement vérifié et je ferais preuve de prudence car il s'exécute avec un accès root complet sur votre hôte), ou vous pouvez créer vos images de docker sans élaguer les conteneurs intermédiaires, puis afficher la différence avec:
# first create and leave containers from any RUN step using options on build
docker image build --rm=false --no-cache -t image_name .
# review which layers use an unexpectedly large amount of space
docker image history image_name
# list all containers, particularly the exited ones from above
docker container ps -a
# examine any of those containers
docker container diff ${container_id}
# ... repeat the diff for other build steps
# then cleanup exited containers
docker container prune
Avec chacun de ces conteneurs intermédiaires, la diff montrera quels fichiers sont ajoutés, modifiés ou supprimés dans cette étape (ceux - ci sont indiqués par un A
, C
ou D
avant chaque nom de fichier). Ce qui diffère est le système de fichiers en lecture / écriture spécifique au conteneur, qui est tout fichier modifié par le conteneur à partir de l'état de l'image à l'aide de la copie sur écriture.
La meilleure façon de réduire la taille de l'image est d'éliminer tous les composants inutiles, comme les compilateurs, de votre image expédiée. Pour cela, les générations en plusieurs étapes vous permettent de compiler en une seule étape, puis de copier uniquement les artefacts résultants de l'étape de génération vers une image d'exécution qui n'a que le minimum nécessaire pour exécuter l'application. Cela évite d'avoir à optimiser l'une des étapes de génération car elles ne sont pas fournies avec l'image résultante.
FROM debian:9 as build
# still chain update with install to prevent stale cache issues
RUN apt-get update \
&& apt-get install -y \
a-package \
wget \
RUN ... # perform any download/compile steps
FROM debian:9-slim as release
COPY --from=build /usr/local/bin/app /usr/local/bin/app
CMD [ "/usr/local/bin/app" ]
Multi-stage est idéal avec des binaires compilés statiquement que vous pouvez exécuter avec scratch comme image de base, ou passer d'un environnement de compilation comme JDK à un environnement d'exécution comme JRE. C'est le moyen le plus simple de réduire considérablement la taille de votre image tout en ayant des constructions rapides. Vous pouvez toujours effectuer le chaînage des étapes de votre étape de publication si vous avez des étapes qui modifient ou suppriment des fichiers créés dans les étapes précédentes, mais pour la plupart, le à COPY
partir d'une autre étape isole l'étape de publication de tout ballonnement de couche rencontré dans les étapes de génération précédentes.
Remarque, je ne recommande pas d'écraser les images car cela réduit la taille d'une image au détriment de la réutilisation des calques. Cela signifie que les futures versions de la même image nécessiteront plus de trafic disque et réseau pour envoyer les mises à jour. Pour revenir au premier exemple, l'écrasement peut réduire votre image de 2 Go à 1 Go, mais pas 3 images peuvent prendre 3 Go au lieu des 2,1 Go.
2.37
contre1.47 GB
Probablement pas exactement une réponse, mais cela vaut la peine de donner les alternatives.
L' habitat du chef a été créé dans cet esprit, créant un package avec toutes les dépendances nécessaires sans la charge d'image distro / base que vous ne souhaitez pas.
Extraits sur ce qui compte ici, la taille du conteneur de ce billet de blog avec une simple application nodejs:
mdfii/node-example
est une image docker d'un fichier docker classique tandis quemfdii/mytutorialapp
l'image docker est produite avec l'habitat.Si la taille est votre principale préoccupation et que vous êtes prêt à suivre la courbe d'apprentissage des plans Habitat, cela pourrait être une solution pour vous.
la source
On pourrait aussi utiliser la plongée
pour obtenir un rapport sur les déchets qui pourraient être supprimés d'une image Docker afin de réduire la taille.
la source
Si vous souhaitez disposer de couches de développement réutilisables tout en réduisant l'utilisation de votre disque pour la livraison, vous pouvez produire une "couche de livraison" fusionnée comme ceci:
docker run IMAGE echo
, si la commande echo est disponible)docker container ls -l
)docker export
pourdocker import
créer le calque fusionné (quelque chose commedocker export 20f192c6530a | docker import - project:merged
)Cela gardera vos couches de développement, mais vous donnera une image fusionnée plus petite que vous pouvez fournir.
la source
Constructions en plusieurs étapes. Utilisez l'image contenant tous vos composants de génération pour créer votre application et une image d'exécution plus légère. Copiez uniquement votre artefact de génération dans l'image d'exécution. Pas besoin de supprimer quoi que ce soit.
https://docs.docker.com/develop/develop-images/multistage-build/
la source
simple .. docker ps vérifier les images en cours d'exécution..pour un exemple de fichier simple ci-dessous ..
DE ubuntu16
MAINTAINER sreeni (email / domaine)
RUN apt-get update
RUN apt-get install -y nginx
ENTRYPOINT ["/ usr / sbin / nginx", "- g", "daemon off;"]
EXPOSE 80 (port)
fichier docker simple ...
utiliser la commande ci-dessous docker
docker run -d -p 80:80 --name web server ubuntu16 (image name) after that check localhost or ip address: 80 (open browser and check)
la source