Как создать большой образ докера с относительно небольшим использованием дискового пространства?
Фон
Я пытаюсь создать образ Docker из Dockerfile на виртуальной машине. Виртуальная машина работает с Redhat 7.1 (ядро 3.10), а Docker - с 1.10.2.
Dockerfile имеет следующий контент
FROM rhel
MAINTAINER MyName<me@email.com>
RUN #yum install wget and other tools (less than 500 MB)
COPY entitlementfile /opt/entitlementfile
RUN wget -O /opt/installer.bin https://installer.com/installer.bin \
&& chmod +x /opt/* \
&& /opt/installer.bin --quiet \
&& rm -f /opt/*.bin
USER admin
Моя сборка VM имеет около 16G свободного места
[root@xrh701 DockerImage]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/rhel-root 18G 2.1G 16G 12% /
...
Установщик около 3G, а установленный пакет около 8G. Это составляет максимум до 11G, немного превышает значения по умолчанию для базового устройства докера, которые составляют 10G.
Поэтому я вручную запускаю демон docker с большим dm.size (15G), чтобы обойти эту проблему.
docker daemon --storage-opt dm.basesize=15G
Поскольку докер основан на Union FS, изображения располагаются друг над другом. Так что я понимаю, что
(1) максимальный размер, который может получить мое изображение, составляет 11G (установщик в одном слое 3G, а слой пакета добавлен поверх 8G)
(2) и если я запустил установщик, запустите его, а затем удалите установщик в той же команде RUN, образ должен быть только 8G (так как установщик 3G удален)
В любом случае, суть в том, что 16G места должно быть более чем достаточно.
проблема
Но мое текущее наблюдение заключается в том, что во время процесса сборки докера он всегда зависал, так как занимал все доступное пространство
[root@xrh701 DockerImage]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/rhel-root 18G 18G 20K 100% /
...
Я вижу два изображения
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> fa09e98656ba About an hour ago 258.1 MB
rhel latest 32f8a1d5f019 9 days ago 203.2 MB
"Проверка докера" показывает, что изображение
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
232245023f90 fa09e98656ba "/bin/sh -c 'wget -O " About an hour ago Exited (0) About an hour ago lonely_curie
Этот промежуточный контейнер завершил выполнение строки wget RUN, успешно завершился, но не зафиксировал образ докера из-за недостатка места
Что еще хуже, я не могу ни удалить контейнер, ни удалить /var/lib/docker, чтобы восстановить пространство назад
# docker rm -f lonely_curie
Failed to remove container (lonely_curie): Error response from daemon: Driver devicemapper failed to remove root filesystem 232245023f90b42a4dbd19a78bf32836f9f8618d7dbcba54159c3df029b5b114: mount still active
Вопрос
Почему докер израсходовал все пространство? Согласно расчету, дискового пространства (16G) должно быть более чем достаточно для целевого изображения (8G). [У меня есть эта виртуальная машина, поэтому я могу гарантировать, что никто другой или какой-либо другой процесс не будет занимать место на жестком диске]
Как принудительно удалить контейнер в моей текущей ситуации, чтобы я мог восстановить пространство обратно?
Как мне создать этот образ 8G (или образ 11G, если вы считаете установщик) на виртуальной машине 16G? Если это невозможно, каково минимальное пространство для его успешной сборки? В настоящее время я подаю заявку на 32G VM из лаборатории.
1 ответ
TL;DR
Предположим, что установщик 3G и установленный пакет 8G.
Если я выпущу Dokcerfile, то для создания этого образа потребуется минимум 22 G [ (3+8)*2 = 22 ].
Если я освобождаю изображение и отправляю его в Dockerhub, то пользователю нужно только 11 G, чтобы вытащить изображение и запустить контейнер на его основе.
================================================== ================
строить
У меня была машина размером около 50G, чтобы перезапустить сборку и контролировать потребление диска.
Перед началом сборки
# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_01-lv_root 59G 6G 53G 9% /
...
После завершения установки
# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_01-lv_root 59G 19G 38G 34% /
...
После того, как изображение передано
# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_01-lv_root 59G 27G 30G 48% /
...
Итак, чтобы ответить на мой собственный вопрос: (1) Он израсходовал весь диск, потому что он требует, по крайней мере, столько места на диске. Предыдущий расчет предполагал, что построенный контейнер и изображение будут иметь один и тот же слой.
(2) Еще не разобрался в этой части. Прямо сейчас я просто выбрасываю ВМ и позволяю вернуть его.
(3) Минимальный требуемый диск будет (3G + 8G) * 2 = 22 ГБ. Поэтому я думаю, что для дальнейшего использования я должен зарезервировать вдвое больше теоретически рассчитанного размера изображения, так как слой представляется скопированным, а не общим при передаче работающего контейнера на изображение. [Создание Dockerfile по сути аналогично ручному запуску контейнера и фиксации изображения.]
================================================== ===============
Бежать
И для продолжения, после того, как я фиксирую образ и удаляю контейнер, диск можно восстановить
# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_01-lv_root 59G 15G 42G 26% /
....
И с этого момента запуск работающего контейнера не увеличит потребление диска (значительно).
# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_01-lv_root 59G 15G 42G 26% /
...