Подтвердить что ты не робот

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

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

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

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

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

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

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

Если мой файл Docker не правдоподобен?

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

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

4b9b3361

Ответ 1

Как сообщает @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, прежде чем уровень будет зафиксирован, или же удалит, фактически не удаляя данные. То есть, в файловой системе union/copy-on-write, очистка в конце не уменьшает использование файловой системы, потому что реальные данные уже привязаны к более низким уровням. Чтобы обойти это, вы должны очищать каждый слой.

$ 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

Ответ 2

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

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

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

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

Ответ 3

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

Я сделал изображение 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 МБ. Это еще меньше, чем исходный размер большинства изображений.

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

Ответ 4

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

  • Избегайте нескольких команд 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 внутри одного файла Docker, и только материал из последнего 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

Ответ 5

Мне многое помогло:

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

  • экспорт docker [containerID] -o containsername.tar
  • docker import -m "commit message here" containsername.tar imagename: tag

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

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

Ответ 6

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

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

Ответ 7

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

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

Ответ 8

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

# 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 без фиксации.