Mengapa gambar wadah Docker begitu besar?

177

Saya membuat gambar sederhana melalui Dockerfile dari Fedora (awalnya 320 MB).

Menambahkan Nano (editor kecil ini berukuran 1MB), dan ukuran gambar telah meningkat hingga 530 MB. Saya telah menambahkan Git di atas itu (30-ish MB), dan kemudian ukuran gambar saya-roket ke 830 MB.

Bukankah itu gila?

Saya sudah mencoba mengekspor dan mengimpor wadah untuk menghapus histori / gambar antara. Upaya ini menghemat hingga 25 MB, sekarang ukuran gambar saya adalah 804 MB. Saya juga telah mencoba menjalankan banyak perintah pada satu RUN, tetapi saya masih mendapatkan 830MB awal yang sama.

Saya ragu apakah layak menggunakan Docker sama sekali. Maksudku, aku hampir tidak menginstal apa pun dan aku memukul lebih dari 1GB. Jika saya harus menambahkan beberapa hal serius seperti database dan sebagainya saya mungkin kehabisan ruang disk.

Adakah yang menderita ukuran gambar yang konyol? Bagaimana Anda menghadapinya?

Kecuali Dockerfile saya salah besar?

FROM fedora:latest
MAINTAINER Me NotYou <[email protected]>
RUN yum -y install nano
RUN yum -y install git

tapi sulit membayangkan apa yang salah di sini.

Zen
sumber
Di mana dan bagaimana Anda mengukur ukuran wadah Anda? Apakah yum clean allada efek pada ukuran?
xeor
2
Harapkan gambar menjadi ukuran yang baik karena ini adalah akumulasi dari gambar itu, gambar induk dan gambar dasar. Juga, Anda menginstal, tidak hanya aplikasi tersebut, tetapi juga dependensinya. docs.docker.com/terms/container
rexposadas
2
Yah "pengukuran" saya adalah eksekusi docker imagesyang pada kolom terakhir menyatakan besar 830MB. Saya mungkin tidak menyadari apa sebenarnya ukuran gambar saya karena perintah gambar buruh pelabuhan menyatakan bahwa 830MB ini adalah ukuran virtual. Tapi sekali lagi, berapa ukuran gambar yang sebenarnya?
Zen

Jawaban:

118

Seperti yang dikatakan @rexposadas, gambar menyertakan semua layer dan setiap layer menyertakan semua dependensi untuk apa yang Anda instal. Penting juga untuk dicatat bahwa gambar dasar (sepertifedora:latest cenderung sangat sederhana). Anda mungkin akan terkejut dengan banyaknya dependensi yang dimiliki oleh perangkat lunak yang Anda instal.

Saya dapat membuat instalasi Anda secara signifikan lebih kecil dengan menambahkan yum -y clean allke setiap baris:

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

Adalah penting untuk melakukan itu untuk setiap RUN, sebelum layer dikomit, atau yang lainnya tidak benar-benar menghapus data. Yaitu, dalam sistem file union / copy-on-write, pembersihan pada akhirnya tidak benar-benar mengurangi penggunaan sistem file karena data nyata sudah berkomitmen untuk lapisan bawah. Untuk menyiasatinya, Anda harus membersihkan setiap lapisan.

$ 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
Andy
sumber
1
Terima kasih atas upaya Anda untuk menyelidiki kasus ini, dan ya saya dapat mengurangi ukuran gambar saya menjadi sekitar 635MB (ini adalah nilai yang disajikan sebagai ukuran gambar virtual setelah eksekusi docker images). Apakah mungkin untuk menghapus / menghapus / menghancurkan layer-layer lama itu? Untuk lebih spesifik: saya ingin benar-benar menghapus (berdasarkan contoh Anda) gambar: 172743bd5d60, 3f2fed40e4b0, fd241224e9cf, 511136ea3c5a dari sejarah, sehingga ukuran gambar virtual saya kurang lebih sama dengan ukuran gambar akhir, di sini ~ 260MB .
Zen
(Terlalu lama untuk 1 komentar) Kecuali ukuran gambar virtual tidak ada hubungannya dengan ukuran gambar sebenarnya pada HDD? Jika ini masalahnya, lalu bagaimana / di mana memeriksa ukuran sebenarnya dari gambar saya?
Zen
Anda bisa docker exportdan sekali docker importlagi. Itu akan meratakan lapisan. Saya tidak berpikir itu akan mengurangi ukuran, tetapi saya bisa saja salah.
Andy
10
Ya tetapi mengekspor tidak menghemat banyak. Meskipun demikian saya bisa membaca melalui web bahwa apa yang dapat saya amati di buruh pelabuhan adalah ukuran gambar virtual. Ukuran aktual pada HDD tampaknya menjadi misteri bagi saya karena sehubungan dengan informasi resmi docker ps -smenunjukkan ukuran nyata pada HDD yang dalam kasus saya adalah -1B. Kedengarannya masuk akal, minus 1 Byte . Saya mendapatkan ruang pada HDD ... tampaknya sah.
Zen
@ Zen Maaf saya tidak mengikuti. Jadi ukuran virtual dan ukuran disk adalah 2 hal yang berbeda? Apa sebenarnya ukuran ukuran virtual?
Jason
63

Gambar Docker tidak besar, Anda hanya membangun gambar besar.

The scratchgambar 0B dan Anda dapat menggunakannya untuk paket sampai kode Anda jika Anda dapat mengkompilasi kode Anda menjadi biner statis. Misalnya, Anda dapat mengkompilasi program Go dan paket itu di atasscratch untuk membuat gambar yang sepenuhnya dapat digunakan kurang dari 5MB.

Kuncinya adalah untuk tidak menggunakan gambar Docker resmi, mereka terlalu besar. Scratch juga tidak terlalu praktis, jadi saya sarankan menggunakan Alpine Linux sebagai gambar dasar Anda. Ini ~ 5MB, maka hanya tambahkan apa yang diperlukan untuk aplikasi Anda. Posting ini tentang Microcontainers menunjukkan kepada Anda bagaimana membangun basis gambar yang sangat kecil di Alpine.

UPDATE: gambar Docker resmi didasarkan pada alpine sekarang sehingga baik untuk digunakan sekarang.

Travis Reeder
sumber
2
Solusi hebat !, sangat penting untuk menghentikan pemborosan dan tetap lebih aman ---> lebih sedikit kode -> kurang khawatir.
Ran Davidovitz
1
Untungnya, gambar Docker Official juga bergerak untuk menggunakan basis Alpine, jadi semakin banyak Anda dapat menggunakan gambar biasa alih-alih bergantung pada versi iron.io. Lihat brianchristner.io/docker-is-moving-to-alpine-linux
Martijn Heemels
@ Travis R, tautan Anda untuk memposting tentang mikrokontroler tampaknya telah pindah ke tempat lain. Apakah ini pos yang ingin Anda tautkan?
Alexander F.
@AlexanderF. Memperbaiki tautan, terima kasih telah memberi tahu saya.
Travis Reeder
28

Berikut beberapa hal yang dapat Anda lakukan :

  • Hindari banyak RUNperintah di mana Anda bisa. Masukkan sebanyak mungkin possbile ke dalam satu RUNperintah (menggunakan &&)
  • bersih-bersih alat yang tidak perlu seperti wget atau git (yang hanya Anda perlukan untuk mengunduh atau membuat barang, tetapi tidak menjalankan proses Anda)

Dengan ini DAN rekomendasi dari @Andy dan @michau saya dapat mengubah ukuran gambar nodejs saya dari 1,062 GB menjadi 542 MB.

Sunting: Satu hal lagi yang penting: "Butuh beberapa saat untuk benar-benar memahami bahwa setiap perintah Dockerfile membuat wadah baru dengan delta. [...] Tidak masalah jika Anda rm -rf file dalam perintah kemudian; mereka terus ada di beberapa wadah lapisan menengah. " Jadi sekarang saya berhasil menempatkan apt-get install, wget, npm install(dengan dependensi git) dan apt-get removemenjadi satuRUN perintah, jadi sekarang gambar saya hanya memiliki 438 MB.

Edit 29/06/17

Dengan Docker v17.06 hadir fitur baru untuk Dockerfiles: Anda dapat memiliki beberapa FROMpernyataan di dalam satu Dockerfile dan hanya hal-hal dari yang terakhir yang FROMakan ada dalam gambar Docker terakhir Anda. Ini berguna untuk mengurangi ukuran gambar, misalnya:

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

Akan menghasilkan gambar yang hanya memiliki gambar dasar nodejs ditambah konten dari / var / my-project dari langkah pertama - tetapi tanpa ruby, python, git, openssh dan gcc!

Munchkin
sumber
22

Ya, ukuran itu konyol, dan saya benar-benar tidak tahu mengapa begitu sedikit orang yang memperhatikan hal itu.

Saya membuat gambar Ubuntu yang sebenarnya minimal (tidak seperti gambar "minimal" lainnya). Disebut textlab/ubuntu-essentialdan memiliki 60 MB.

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

Gambar di atas adalah 82 MB setelah menginstal nano.

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

Git memiliki lebih banyak prasyarat, sehingga gambarnya menjadi lebih besar, sekitar 192 MB. Itu masih kurang dari ukuran awal sebagian besar gambar.

Anda juga dapat melihat skrip yang saya tulis untuk membuat gambar Ubuntu minimal untuk Docker . Anda mungkin dapat mengadaptasinya ke Fedora, tetapi saya tidak yakin seberapa banyak Anda dapat menghapus.

michau
sumber
13

Berikut ini banyak membantu saya:

Setelah menghapus paket yang tidak digunakan (mis. Redis 1200 mb dibebaskan) di dalam wadah saya, saya telah melakukan hal berikut:

  1. ekspor buruh pelabuhan [containerID] -o containername.tar
  2. impor buruh pelabuhan -m "komit pesan di sini" containername.tar imagename: tag

Lapisan menjadi rata. Ukuran gambar baru akan lebih kecil karena saya telah menghapus paket dari wadah seperti yang disebutkan di atas.

Ini membutuhkan banyak waktu untuk memahami hal ini dan itulah sebabnya saya menambahkan komentar saya.

Jeffrey Schmitz
sumber
Anda dapat menggabungkan kedua langkah menjadi satu langkahdocker export <CONTAINER ID> | docker import - some-image-name:latest
Anuj Kumar
8

Untuk praktik terbaik, Anda harus menjalankan perintah RUN tunggal, karena setiap instruksi RUN di Dockerfile menulis lapisan baru pada gambar dan setiap lapisan membutuhkan ruang ekstra pada disk. Untuk menjaga agar jumlah layer minimum, manipulasi file seperti menginstal, memindahkan, mengekstraksi, menghapus, dll, idealnya harus dibuat di bawah instruksi RUN tunggal

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

Docker Squash adalah solusi yang sangat bagus untuk ini. kamu bisa$packagemanager clean pada langkah terakhir alih-alih di setiap baris dan kemudian jalankan squash buruh pelabuhan untuk menyingkirkan semua layer.

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

jeremyjjbrown
sumber
0

Ya sistem lapisannya cukup mengejutkan. Jika Anda memiliki gambar dasar dan Anda menambahkannya dengan melakukan hal berikut:

# 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/* 

Gambar memiliki ukuran yang persis sama. Itu pada dasarnya berarti, Anda harus mengatur untuk menjalankan langkah-langkah RUN Anda banyak mengekstrak, menginstal dan membersihkan sihir untuk membuat gambar sekecil perangkat lunak yang diinstal.

Ini membuat hidup jauh lebih sulit ...

DockerBuild tidak memiliki langkah RUN tanpa komit.

99Sono
sumber