Почему изображения контейнера Docker такие большие?

177

Я сделал простой образ через Dockerfile из Fedora (изначально 320 МБ).

Добавлен Nano (этот крошечный редактор размером 1 МБ), и размер изображения увеличился до 530 МБ. Кроме того, я добавил Git (30 МБ), а затем увеличил размер моего изображения до 830 МБ.

Разве это не безумие?

Я пытался экспортировать и импортировать контейнер для удаления истории / промежуточных изображений. Это усилие сэкономило до 25 МБ, теперь мой размер изображения составляет 804 МБ. Я также пытался запустить много команд на одной RUN, но все же я получаю те же начальные 830 МБ.

У меня есть сомнения, стоит ли вообще использовать Docker. Я имею в виду, я едва что-то установил, и я ударил 1 Гб сверх. Если мне придется добавить некоторые серьезные вещи, такие как база данных и т. Д., У меня может быть недостаточно места на диске.

Кто-нибудь страдает от нелепого размера изображений? Как вы справляетесь с этим?

Разве мой Dockerfile ужасно неверен?

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

но трудно представить, что здесь может пойти не так.

Zen
источник
Где и как вы измеряете размер вашего контейнера? Имеет ли yum clean allкакое-либо влияние на размер?
xeor
2
Ожидайте, что изображения будут хорошего размера, так как это совокупность их изображений, родительских изображений и базового изображения. Кроме того, yum устанавливает не только указанные приложения, но и их зависимости. docs.docker.com/terms/container
rexposadas
2
Что ж, мое «измерение» - это выполнение, в docker imagesкотором в последнем столбце говорится о здоровенных 830 МБ. Возможно, я не знаю, каков фактический размер моего образа, поскольку команда docker images утверждает, что эти 830 МБ виртуального размера. Но опять же, каков реальный размер изображения?
Дзен

Ответы:

118

Как сказал @rexposadas, изображения включают в себя все слои, и каждый слой включает в себя все зависимости для того, что вы установили. Также важно отметить, что базовые образы (например, fedora:latestобычно очень скудны). Вы можете быть удивлены количеством зависимостей, которые имеет установленное программное обеспечение.

Я смог сделать вашу установку значительно меньше, добавив yum -y clean allв каждую строку:

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

Важно сделать это для каждого RUN, перед тем как уровень будет зафиксирован, иначе удаление не приведет к удалению данных. Таким образом, в файловой системе объединения / копирования при записи очистка в конце фактически не уменьшает использование файловой системы, поскольку реальные данные уже передаются на более низкие уровни. Чтобы обойти это, вы должны очистить каждый слой.

$ 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
Спасибо за ваши усилия по расследованию дела, и да, мне удалось уменьшить размер моего изображения примерно до 635 МБ (это значение представлено как размер виртуального изображения после выполнения docker images). Можно ли удалить / удалить / уничтожить эти старые слои? Чтобы быть более конкретным: я хотел бы полностью удалить (основываясь на вашем примере) изображения: 172743bd5d60, 3f2fed40e4b0, fd241224e9cf, 511136ea3c5a из истории, так что размер моего виртуального изображения более-менее совпадает с окончательным размером, здесь ~ 260 МБ ,
Дзен
(Слишком долго для 1 комментария) Разве размер виртуального изображения не имеет ничего общего с фактическим размером изображения на жестком диске? Если это так, то как / где проверить фактический размер моих изображений?
Дзен
Вы могли бы docker exportи тогда docker importснова. Это сгладит слои. Я не думаю, что это уменьшит размер, но я могу ошибаться.
Энди
10
Да, но экспорт не сильно экономит. Тем не менее я смог прочитать в Интернете, что в докере я могу наблюдать размер виртуального образа. Реальный размер жесткого диска кажется мне загадкой, поскольку в отношении официальной информации docker ps -sуказан реальный размер жесткого диска, который в моем случае был -1B. Звучит разумно, минус 1 байт . Я получил немного места на жестком диске ... кажется законным.
Дзен
@Zen Извините, я не подписан. Таким образом, виртуальный размер и размер диска - это две разные вещи? Что именно измеряет виртуальный размер?
Джейсон
63

Изображения Docker не большие, вы просто создаете большие изображения.

scratchИзображение 0B , и вы можете использовать, чтобы упаковать свой код , если вы можете скомпилировать код в статический бинарный. Например, вы можете скомпилировать вашу программу Go и упаковать ее сверху,scratch чтобы получить полностью пригодное для использования изображение размером менее 5 МБ.

Ключ в том, чтобы не использовать официальные изображения Docker, они слишком велики. Скретч не так уж практичен, поэтому я бы рекомендовал использовать Alpine Linux в качестве базового образа. Это ~ 5 МБ, тогда добавьте только то, что требуется для вашего приложения. Этот пост о микроконтейнерах покажет вам, как создать очень маленькую базу изображений на Alpine.

ОБНОВЛЕНИЕ: официальные изображения Docker теперь основаны на альпийском, так что теперь их удобно использовать.

Трэвис Ридер
источник
2
Отличное решение !, так важно остановить отходы и оставаться более защищенными ---> меньше кода -> меньше беспокоиться.
Ран Давидовиц
1
К счастью, официальные изображения Docker также переходят на использование базы Alpine, поэтому все больше и больше вы можете использовать обычные изображения вместо того, чтобы зависеть от версий iron.io. См. Brianchristner.io/docker-is-moving-to-alpine-linux
Мартейн Химельс
@ Travis R, ваша ссылка на пост о микроконтейнерах, похоже, переместилась куда-то еще. Является ли это пост вы хотели ссылку?
Александр Федорович
@AlexanderF. Исправлены ссылки, спасибо, что сообщили мне.
Трэвис Ридер
28

Вот еще несколько вещей, которые вы можете сделать :

  • Избегайте нескольких RUNкоманд, где вы можете. Положите как можно больше в одну RUNкоманду (используя &&)
  • очистите ненужные инструменты, такие как wget или git (которые нужны только для загрузки или сборки, но не для запуска процесса)

Благодаря этим обоим и рекомендациям @Andy и @michau я смог изменить размер своего изображения nodejs с 1,062 ГБ до 542 МБ.

Изменить: Еще одна важная вещь: «Мне потребовалось некоторое время, чтобы понять, что каждая команда Dockerfile создает новый контейнер с дельтами. [...] Не имеет значения, если вы rm -rf файлы в более поздней команде; они продолжают существовать в каком-то контейнере промежуточного слоя ". Так что теперь мне удалось поставить apt-get install, wget, npm install(с GIT зависимостей) и apt-get removeв одной RUNкоманде, так что теперь мое изображение имеет только 438 МБ.

Изменить 29/06/17

С Docker v17.06 появились новые функции для Dockerfiles: вы можете иметь несколько FROMоператоров в одном Dockerfile, и только последний материал FROMбудет в вашем окончательном образе Docker. Это полезно для уменьшения размера изображения, например:

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

В результате изображение будет иметь только базовое изображение nodejs плюс содержимое из / var / my-project с первых шагов - но без ruby, python, git, openssh и gcc!

Манчкин
источник
22

Да, эти размеры смешны, и я действительно не знаю, почему так мало людей это замечают.

Я сделал образ Ubuntu, который на самом деле минимален (в отличие от других так называемых «минимальных» изображений). Он называется textlab/ubuntu-essentialи имеет 60 МБ.

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

Изображение выше 82 МБ после установки nano.

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

У Git гораздо больше предпосылок, поэтому размер изображения увеличивается, около 192 МБ. Это еще меньше, чем первоначальный размер большинства изображений.

Вы также можете взглянуть на сценарий, который я написал, чтобы создать минимальный образ Ubuntu для Docker . Возможно, вы можете адаптировать его для Fedora, но я не уверен, сколько вы сможете удалить.

michau
источник
13

Следующее мне очень помогло:

После удаления неиспользуемых пакетов (например, redis 1200 mb освобождается) из моего контейнера, я сделал следующее:

  1. docker export [containerID] -o containername.tar
  2. docker import -m "зафиксировать здесь сообщение"

Слои становятся плоскими. Размер нового изображения будет меньше, потому что я удалил пакеты из контейнера, как указано выше.

Потребовалось много времени, чтобы понять это, и поэтому я добавил свой комментарий.

Джеффри Шмитц
источник
Вы можете объединить оба шага в один шагdocker export <CONTAINER ID> | docker import - some-image-name:latest
Анудж Кумар
8

Для лучшей практики вы должны выполнить одну команду RUN, потому что каждая инструкция RUN в Dockerfile записывает новый слой в образ, и каждый слой требует дополнительного места на диске. Чтобы свести к минимуму количество слоев, любые манипуляции с файлами, такие как установка, перемещение, извлечение, удаление и т. Д., В идеале должны выполняться в одной инструкции RUN.

FROM fedora:latest
RUN yum -y install nano git && yum -y clean all
tmz83
источник
4

Docker Squash - действительно хорошее решение для этого. Вы можете $packagemanager cleanна последнем шаге вместо каждой строки, а затем просто запустить сквош докера, чтобы избавиться от всех слоев.

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

jeremyjjbrown
источник
0

Да, система слоев довольно удивительна. Если у вас есть базовое изображение, и вы увеличиваете его, выполняя следующие действия:

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

Изображение имеет точно такой же размер. По сути, это означает, что вам нужно уметь вкладывать в свои шаги RUN много магии извлечения, установки и очистки, чтобы сделать изображения такими же маленькими, как и установленное программное обеспечение.

Это делает жизнь намного сложнее ...

В dockerBuild отсутствуют шаги RUN без коммита.

99Sono
источник