Perché le immagini del contenitore Docker sono così grandi?


177

Ho creato un'immagine semplice tramite Dockerfile di Fedora (inizialmente 320 MB).

Aggiunto Nano (questo piccolo editor di dimensioni di 1 MB) e la dimensione dell'immagine è salita a 530 MB. Ho aggiunto Git sopra a quello (30-ish MB), quindi le dimensioni della mia immagine sono salite a 830 MB.

Non è folle?

Ho provato a esportare e importare container per rimuovere la cronologia / le immagini intermedie. Questo sforzo ha permesso di risparmiare fino a 25 MB, ora la mia dimensione dell'immagine è 804 MB. Ho anche provato a eseguire molti comandi su uno RUN, ma sto ancora ricevendo gli stessi 830 MB iniziali.

Sto avendo dei dubbi se vale la pena usare Docker. Voglio dire, ho appena installato nulla e sto colpendo 1 GB. Se dovessi aggiungere alcune cose serie come un database e così via, potrei esaurire lo spazio su disco.

Qualcuno soffre di ridicole dimensioni delle immagini? Come lo gestisci?

A meno che il mio Dockerfile non sia terribilmente errato?

FROM fedora:latest
MAINTAINER Me NotYou <email@dot.com>
RUN yum -y install nano
RUN yum -y install git

ma è difficile immaginare cosa potrebbe andare storto qui.


Dove e come stai misurando le dimensioni del tuo contenitore? Ha yum clean allqualche effetto sulla dimensione?
xeor,

2
Aspettatevi che le immagini siano di buone dimensioni poiché si tratta di un accumulo di immagini, immagini principali e immagine di base. Inoltre, yum installa, non solo le suddette app, ma anche le loro dipendenze. docs.docker.com/terms/container
rexposadas

2
Bene, la mia "misurazione" è l'esecuzione di docker imagescui nell'ultima colonna indica un pesante 830 MB. Potrei essere ignaro del fatto quale sia la dimensione effettiva della mia immagine poiché il comando docker images afferma che questo 830 MB è una dimensione virtuale. Ma poi di nuovo, qual è la dimensione reale dell'immagine?
Zen,

Risposte:


118

Come diceva @rexposadas, le immagini includono tutti i livelli e ogni livello include tutte le dipendenze per ciò che hai installato. È anche importante notare che le immagini di base (come quelle fedora:latesttendenzialmente sono molto spoglie. Potresti essere sorpreso dal numero di dipendenze che il tuo software installato ha.

Sono stato in grado di ridurre notevolmente la tua installazione aggiungendo yum -y clean alla ciascuna riga:

FROM fedora:latest
RUN yum -y install nano && yum -y clean all
RUN yum -y install git && yum -y clean all

È importante farlo per ogni RUN, prima che il layer venga impegnato, altrimenti le eliminazioni non rimuovono effettivamente i dati. Cioè, in un file system union / copy-on-write, la pulizia alla fine non riduce realmente l'utilizzo del file system perché i dati reali sono già impegnati nei livelli inferiori. Per ovviare a questo è necessario pulire ad ogni livello.

$ 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

1
Grazie per il vostro sforzo di indagare sul caso e sì, sono stato in grado di ridurre le dimensioni dell'immagine a circa 635 MB (questo è il valore presentato come dimensione dell'immagine virtuale dopo l'esecuzione di docker images). È possibile rimuovere / cancellare / distruggere quei vecchi livelli? Per essere più specifici: vorrei rimuovere completamente (sulla base del tuo esempio) immagini: 172743bd5d60, 3f2fed40e4b0, fd241224e9cf, 511136ea3c5a dalla storia, in modo che le dimensioni della mia immagine virtuale siano più o meno le stesse dell'immagine finale, qui ~ 260 MB .
Zen,

(Troppo lungo per 1 commento) A meno che la dimensione dell'immagine virtuale non abbia nulla a che fare con la dimensione effettiva dell'immagine sull'HDD? In questo caso, come / dove controllare le dimensioni effettive delle mie immagini?
Zen,

Potresti docker exporte poi di docker importnuovo. Ciò appiattirebbe gli strati. Non penso che ridurrebbe le dimensioni, ma potrei sbagliarmi.
Andy,

10
Sì, ma l'esportazione non risparmia molto. Tuttavia sono riuscito a leggere attraverso il web che ciò che posso osservare nella finestra mobile è la dimensione dell'immagine virtuale. Le dimensioni effettive su HDD sembrano essere un mistero per me poiché rispetto alle informazioni ufficiali docker ps -smostrano dimensioni reali su HDD che nel mio caso lo erano -1B. Sembra ragionevole, meno 1 byte . Ho guadagnato un po 'di spazio su HDD ... sembra legittimo.
Zen,

@Zen Mi dispiace non sto seguendo. Quindi la dimensione virtuale e la dimensione del disco sono 2 cose diverse? Cosa misura esattamente la dimensione virtuale?
Jason,

63

Le immagini docker non sono grandi, stai solo costruendo immagini di grandi dimensioni.

L' scratchimmagine è 0B e puoi usarla per impacchettare il tuo codice se puoi compilare il tuo codice in un binario statico. Ad esempio, puoi compilare il tuo programma Go e impacchettarlo soprascratch per creare un'immagine completamente utilizzabile che sia inferiore a 5 MB.

La chiave è non usare le immagini Docker ufficiali, sono troppo grandi. Scratch non è neanche così pratico, quindi consiglierei di utilizzare Alpine Linux come immagine di base. È ~ 5 MB, quindi aggiungi solo ciò che è necessario per la tua app. Questo post su Microcontainer mostra come costruire immagini di dimensioni molto ridotte su Alpine.

AGGIORNAMENTO: le immagini Docker ufficiali sono basate su alpine ora, quindi sono buone da usare ora.


2
Ottima soluzione !, È così importante fermare i rifiuti e rimanere più sicuri ---> meno codice -> meno preoccupazioni.
Ran Davidovitz,

1
Per fortuna, anche le immagini ufficiali Docker si stanno muovendo per utilizzare una base alpina, quindi è sempre più possibile utilizzare le immagini normali invece di dipendere dalle versioni di iron.io. Vedi brianchristner.io/docker-is-moving-to-alpine-linux
Martijn Heemels,

@Travis R, il tuo link per pubblicare post sui microcontenitori sembra essersi spostato altrove. È questo il post che intendevi collegare?
Alexander F.

@AlexanderF. Collegamenti fissi, grazie per avermelo fatto notare.
Travis Reeder,

28

Ecco alcune altre cose che puoi fare :

  • Evita più RUNcomandi dove puoi. Metti tutto il possibile in un RUNcomando (usando &&)
  • ripulisci gli strumenti non necessari come wget o git (di cui hai solo bisogno per scaricare o creare cose, ma non per eseguire il tuo processo)

Con entrambi i consigli AND di @Andy e @michau sono stato in grado di ridimensionare la mia immagine nodejs da 1.062 GB a 542 MB.

Modifica: Un'altra cosa importante: "Mi ci è voluto un po 'di tempo per capire davvero che ogni comando Dockerfile crea un nuovo contenitore con i delta. [...] Non importa se rm -rf i file in un comando successivo; continuano a esistere in alcuni container di livello intermedio ". Così ora sono riuscito a mettere apt-get install, wget, npm install(con le dipendenze Git) e apt-get removein un unico RUNcomando, così ora la mia immagine ha solo 438 MB.

Modifica 29/06/17

Con Docker v17.06 sono disponibili nuove funzionalità per i file Docker: è possibile avere più FROMistruzioni all'interno di un file Docker e solo i contenuti dell'ultimo FROMsaranno nell'immagine Docker finale. Ciò è utile per ridurre le dimensioni dell'immagine, ad esempio:

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

Si tradurrà in un'immagine che ha solo l'immagine di base nodejs più il contenuto di / var / my-project sin dai primi passi - ma senza ruby, python, git, openssh e gcc!


22

Sì, quelle dimensioni sono ridicole e non ho davvero idea del perché così poche persone lo notino.

Ho creato un'immagine di Ubuntu che è in realtà minima (a differenza di altre cosiddette immagini "minimal"). Si chiama textlab/ubuntu-essentiale ha 60 MB.

FROM textlab/ubuntu-essential
RUN apt-get update && apt-get -y install nano

L'immagine sopra è di 82 MB dopo l'installazione di nano.

FROM textlab/ubuntu-essential
RUN apt-get update && apt-get -y install nano git

Git ha molti più prerequisiti, quindi l'immagine diventa più grande, circa 192 MB. Questo è ancora inferiore alla dimensione iniziale della maggior parte delle immagini.

Puoi anche dare un'occhiata allo script che ho scritto per creare l'immagine minima di Ubuntu per Docker . Puoi forse adattarlo a Fedora, ma non sono sicuro di quanto sarai in grado di disinstallare.


13

Quanto segue mi ha aiutato molto:

Dopo aver rimosso i pacchetti non utilizzati (ad es. Redis 1200 mb liberati) all'interno del mio contenitore, ho fatto quanto segue:

  1. docker export [containerID] -o containerername.tar
  2. docker import -m "commit del messaggio qui" contiene username.tar imagename: tag

Gli strati si appiattiscono. Le dimensioni della nuova immagine saranno inferiori perché ho rimosso i pacchetti dal contenitore come indicato sopra.

Ci è voluto molto tempo per capirlo ed è per questo che ho aggiunto il mio commento.


Puoi combinare entrambi i passaggi in un unico passaggiodocker export <CONTAINER ID> | docker import - some-image-name:latest
Anuj Kumar il

8

Per la migliore pratica, è necessario eseguire un singolo comando RUN, poiché ogni istruzione RUN nel Dockerfile scrive un nuovo livello nell'immagine e ogni livello richiede spazio aggiuntivo sul disco. Al fine di ridurre al minimo i livelli numerici, qualsiasi manipolazione di file come installazione, spostamento, estrazione, rimozione, ecc. Dovrebbe idealmente essere effettuata con una singola istruzione RUN

FROM fedora:latest
RUN yum -y install nano git && yum -y clean all


0

Sì, il sistema a strati è abbastanza sorprendente. Se si dispone di un'immagine di base e la si incrementa nel modo seguente:

# 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'immagine ha esattamente le stesse dimensioni. Ciò significa essenzialmente che devi riuscire a mettere nelle tue fasi RUN un sacco di estrazione, installazione e pulizia magica per rendere le immagini piccole quanto il software installato.

Questo rende la vita molto più difficile ...

Nel dockerBuild mancano i passaggi RUN senza commit.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.