Как добавить элементы в .dockerignore?
Я не могу найти много примеров того, как должен выглядеть файл .dockerignore.
Использование марионетки для установки нескольких пакетов на контейнере докера приводит к тому, что изображение взорвалось от 600 МБ до 3 ГБ. Я пытаюсь использовать файл .dockerignore
, чтобы сохранить размер в minumum
$ cat Dockerfile
FROM centos:centos6
#Work around selinux problem on cent images
RUN yum install -y --enablerepo=centosplus libselinux-devel
RUN yum install -y wget git tar openssh-server; yum -y clean all
Add Puppetfile /
RUN librarian-puppet install
RUN puppet apply --modulepath=/modules -e "class { 'buildslave': jenkins_slave => true,}"
RUN librarian-puppet clean
Если я запустил docker images --tree
, я вижу, что изображение мгновенно растет на несколько GB
$ docker images --tree
├─e289570b5555 Virtual Size: 387.7 MB
│ └─a7646acf90d0 Virtual Size: 442.5 MB
│ └─d7bc6e1fbe43 Virtual Size: 442.5 MB
│ └─772e6b204e3b Virtual Size: 627.5 MB
│ └─599a7b5226f4 Virtual Size: 627.5 MB
│ └─9fbffccda8bd Virtual Size: 2.943 GB
│ └─ee46af013f6b Virtual Size: 2.943 GB
│ └─3e4fe065fd07 Virtual Size: 2.943 GB
│ └─de9ec3eba39e Virtual Size: 2.943 GB
│ └─31cba2716a12 Virtual Size: 2.943 GB
│ └─52cbc742d3c4 Virtual Size: 2.943 GB
│ └─9a857380258c Virtual Size: 2.943 GB
│ └─c6d87a343807 Virtual Size: 2.964 GB
│ └─f664124e0080 Virtual Size: 2.964 GB
│ └─e6cc212038b9 Virtual Size: 2.964 GB Tags: foo/jenkins-centos6-buildslave:latest
Я полагаю, что причина, по которой изображение растет настолько велико, состоит в том, что librarian-puppet
клонирует кукольный модуль на /modules
, который разбивает кеш сборки
Я пробовал следующие .dockerignore
файлы без везения.
$ cat .dockerignore
/modules
/modules/
/modules/*
Является ли это правильным синтаксисом для файла .dockerignore
?
Существуют ли другие способы предотвращения роста этих контейнеров?
Дополнительная информация:
http://kartar.net/2013/12/building-puppet-apps-inside-docker/
http://danielmartins.ninja/posts/a-week-of-docker.html
Ответы
Ответ 1
.dockerignore
заключается в том, чтобы запретить добавление файлов в исходный контекст сборки, который отправляется демону docker, когда вы выполняете docker build
, он не создает глобальное правило для исключения файлов из всех созданных изображений с помощью файла Docker.
Важно отметить, что каждый оператор RUN
генерирует новое изображение, причем родителем этого образа является образ, сгенерированный над ним надписью Dockerfile. Попробуйте свернуть ваши операторы RUN
в один, чтобы уменьшить размер изображения:
RUN librarian-puppet install &&\
puppet apply --modulepath=/modules -e "class { 'buildslave': jenkins_slave => true,}" &&\
librarian-puppet clean
Ответ 2
Формат .dockerignore
должен совпадать с .gitignore
. Смотрите образец файла и док-документацию.
Файл должен представлять собой список шаблонов исключений (относительно пути к файлу .dockerignore
), разделенных новой .dockerignore
.
Поэтому вы должны попробовать следующее .dockerignore
:
modules/*
/
В начале, возможно, была ошибкой, поскольку она будет действительна только для корневого каталога файла (но не для подкаталогов, поэтому, возможно, рекурсивная версия без /
сделает лучшую работу вместо этого).
Ответ 3
Ни:
modules/*
ни
modules
не работает для меня, докер продолжает загрязнять изображение ненужными файлами, пока не установлю его так:
**/modules
также работает с:
**/modules/*.py
Ответ 4
Другой способ сделать это, создавая меньшее изображение, - это запустить библиотечный куклу в хосте, а не в Docker, так что вы не заканчивайтесь библиотекой, рубином, драгоценными камнями,... установленными на изображении.
Я закончил с изображением 622 МБ для jenkins slave using Puppet и 480MB образ без Puppet.
Ответ 5
http://docs.docker.com/articles/dockerfile_best-practices/
Мне кажется, что ваш подход в обратном направлении (согласие с @csanchez), и что вы должны создавать свой контейнер для докеров из марионетки, а не запускать куклу в контейнере...
Кроме того, вы должны &&
установить/применить/очистить строки вместе... каждая команда docker создает инкрементное изображение... Если есть временные/ресурсные файлы, которые являются частью команд centos yum
, вы также должны сделать то же самое.
FROM centos:centos6
# Add your needed files first
# maybe you could use a baseimage and make this a volume mount point?
Add Puppetfile /
# combine multiple commands with cleanup of cache/temporary
# space in the same run sequence to reduce wasted diff image space.
#Work around selinux problem on cent images
RUN yum install -y --enablerepo=centosplus libselinux-devel && \
yum install -y wget git tar openssh-server; yum -y clean all && \
librarian-puppet install && \
puppet apply --modulepath=/modules -e "class { 'buildslave': jenkins_slave => true,}" && \
librarian-puppet clean
Я бы ДЕЙСТВИТЕЛЬНО предложил избегать SELINUX в контейнере, он не дает вам ничего внутри контейнера. Не говоря уже о том, что в зависимости от того, что вы пытаетесь создать, есть меньше мест для начала, чем centos6. Я считаю, что ubuntu меньше, debian: wheezy меньше по-прежнему или даже альпийский для крошечной начальной точки.
Стоит отметить, что ваш размер файла, если вы используете файловую систему, поддерживающую виртуальные монтировки, может повторно использовать одно и то же базовое изображение для нескольких экземпляров, поэтому он не будет больше
Ответ 6
Оптимизация размера изображения контейнера является основной целью .dockerignore, поскольку она служит цели, аналогичной вашей .gitignore, поскольку она уменьшает время ожидания и время отклика при предоставлении Сервисы. Это верно для автоматизации развертывания, такой как Puppet, SaltStack или Ansible. Временная метка, определенная для развертывания выполнения службы, может быть неудачной из-за большего размера изображения и низкой пропускной способности сети. Таким образом .dockerignore помогает сделать размер изображения как можно меньшим.
Вы можете поместить его в каталог build context, который мы укажем в конце команды сборки docker. Файл следует за glob шаблон для файлов и каталогов, чтобы исключить их из окончательного образа сборки.
Предположим, что у меня есть каталог. img/ в мой контекст сборки, и я хочу исключить его при создании образа, я просто добавлю следующую строку в файл .dockerignore,
.img
И, если я хочу исключить все файлы, начинающиеся с. то просто добавьте строку,
.*
(Примечание. Не путайте шаблон шара Unix, отличный от регулярных выражений)
Кроме того, я исключу несколько моих файлов из контекста сборки,
.*
docs
my-stack.dab
docker-compose.overrride.yml
test*
*.md
!README.md
Здесь строка *.md исключает все файлы разметки (у меня есть много файлов разметки в моем проекте). Но я хочу включить README.md и никаких других файлов разметки. Как наша последняя строка выше, мы добавили README.md с ! или исключили ее, исключив все другие файлы разметки.
Итак, с этим мы можем уменьшить накладные расходы вашего образа сборки с помощью .dockerignore и использовать рычаги, чтобы уменьшить размер изображения.
Ответ 7
Я думаю, что лучшим решением для вашего случая использования является использование многоступенчатой сборки в вашем файле Docker. Ваш Dockerfile должен находиться в пустой директории, а вы запускаете puppet в одноразовом контейнере.
По ссылке выше:
В многоэтапных сборках вы используете несколько операторов FROM в вашем Dockerfile. Каждая инструкция FROM может использовать различную базу, и каждая из них начинает новый этап сборки. Вы можете выборочно копировать артефакты с одного этапа на другой, оставляя после себя все, что вам не нужно, в конечном изображении.
Ответ 8
Файл .dockerignore
аналогичен синтаксису .gitignore
. Вот несколько примеров правил:
# Ignore a file or directory in the context root named "modules"
modules
# Ignore any files or directories within the subdirectory named "modules"
# in the context root
modules/*
# Ignore any files or directories in the context root beginning with "modules"
modules*
# Ignore any files or directories one level down from the context root named
# "modules"
*/modules
# Ignore any files or directories at any level, including the context root,
# named modules
**/modules
# Ignore every file in the entire build context (see next rule for how this
# could be used)
*
# Re-include the file or directory named "src" that may have been previously
# excluded. Note that you cannot re-include files in subdirectories that have
# been previously excluded at a higher level
!src
Обратите внимание, что "контекст сборки" - это каталог, который вы передаете в конце вашей команды сборки, обычно a .
указать текущий каталог. Этот каталог упаковывается из клиента докера, за исключением любых файлов, которые вы проигнорировали с помощью .dockerignore
, и отправляется демону docker для выполнения сборки. Даже если демон находится на том же хосте, что и ваш клиент, сборка работает только из этого контекста, а не напрямую из папок.
Для сборки существует только один .dockerignore
, и он должен находиться в корне контекста сборки. Он не будет работать, если он находится в вашем домашнем каталоге (предполагается, что вы создаете из подкаталога), и не будет работать из подкаталога вашего контекста сборки.
Чтобы проверить, что находится в текущем контексте сборки, и убедиться, что файл .dockerignore
работает правильно, вы можете скопировать/вставить следующее (предполагается, что у вас нет изображения с именем test-context
, оно будет перезаписано и затем удалено, если вы это сделаете ):
# create an image that includes the entire build context
docker build -t test-context -f - . <<EOF
FROM busybox
COPY . /context
WORKDIR /context
CMD find .
EOF
# run the image which executes the find command
docker container run --rm test-context
# cleanup the built image
docker image rm test-context