Как добавить элементы в .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