Согласитесь, хранить образ Nginx размером в 200+ Мбайт. на базе Debian 9 — довольно накладно, поэтому рассмотрим 5 приемов по уменьшению размера собираемых образов.
Прием 1 — уменьшаем количество слоев в образе
Уменьшить количество слоев в образе можно сворачиванием нескольких однородных инструкций в одну. Например, несколько логически связанных инструкций RUN можно объединить в одну инструкцию с помощью конвейера Linux:
RUN apt-get update && apt-get install -y nginx
Об этом приеме мы не раз упоминали в статье «Введение в Docker: образы, контейнеры и докер-файлы». Если вы ещё не читали нашу статью — рекомендуем с ней ознакомиться.
Прием 2 — удаляем ненужный кэш apt-get
Пакетный менеджер apt-get, обновляя репозиторий, сохраняет кэш, который в большинстве случаев не нужен, и его можно удалить, уменьшив тем самым собираемый образ на 100+ Мбайт. Сделать это совсем несложно, достаточно в инструкции RUN последней командой указать: && rm -f /var/lib/apt/lists/*.
Соединим оба приёма в одну инструкцию:
RUN apt-get update && apt-get install -y nginx && rm -f /var/lib/apt/lists/*
Такая конструкция работает именно в одной инструкции RUN, если вы вынесете rm -f /var/lib/apt/lists/* в отдельный RUN — ничего не сработает, так как кеш будет очищаться в другом слое, а его обновление будет оставаться в предыдущем слое.
Прием 3 — копируем только нужные файлы проекта в образ с помощью .dockerignore-файла
Обычно для копирования проекта в образ используется инструкция COPY с указанием места расположения проекта, как «.», что указывает на текущею директорию. Такой подход имеет один недостаток — будут скопированы все вложенные подкаталоги и файлы, что может значительно увеличить размер образа.
Исправить ситуацию призван .dockerignore-файл, который работает так же как и .gitignore-файл. В этих файлах указываются те папки и файлы, которые «не надо трогать». Gitignore-файл располагается в корневом каталоге копируемого в образ проекта. Обратите внимание на точку в начале названия файла — «.gitignore», так и должно быть.
Рассмотрим пример работы .gitignore-файла. Например, мы работаем с GIT, и в нашем проекте есть GIT-репозиторий. В образе он нам не нужен, поэтому его можно не копировать, а ещё в образе нам не нужен Dockerfile. Укажем эти файлы в .gitignore-файле:
.GIT
Dockerfile
При сборке образа Docker прочтет .dockerignore-файл и не включит в образ указанные в нем папки и файлы.
Приём 4 — используем минималистические Linux-образа Alpine
Как правило, для сборки образов применяются дистрибутивы Debian, Ubuntu, CentOS. Но это оправдано в том случае, если ваш проект будет использовать всё обилие возможностей ядра и пакетов, которые предоставляет выбранный дистрибутив. Если же вам нужно просто создать контейнер с Nginx или иной другой программой — используйте Alpine-сборки.
Alpine-образ весит считанные мегабайты, а не сотни Мбайт как Debian или Ubuntu, при этом в нём есть всё необходимое для запуска большинства приложений. Например, так выглядит dockerfile Nginx-образа на Alpine-сборке, который занимает 7 Мбайт:
FROM alpine
RUN apk add --no-cache nginx && mkdir -p /run/nginx
EXPOSE 80
COPY custom.conf /etc/nginx/conf.d
dockerCOPY . /opt/
CMD ["nginx”,”-g”,”daemon off;”]
Еще один бесспорный плюс Alpine — скорость сборки образа. Она разительно отличается в лучшую сторону по сравнению со скоростью сборки на любом другом дистрибутиве Linux.
Прием 5 — часто изменяемые слои ставим в конец dockerfile
Слоистая структура Docker-образов имеет одно неприятное свойство — при внесении изменения в один из слоев, это слой и все последующие слои будут пересобраны. Поэтому, чтобы сэкономить время на сборке образа — старайтесь ставить инструкции копирования кода проекта и конфигов в конец dockerfile до команды CMD или ENTRYPOINT.
Если вы интересуетесь Docker и контейнеризацией в целом, вам могут быть интересны следующие материалы:
История контейнеризации
Краткая история контейнеризации и разбор конкретных технологий: chroot, jail, namespaces и cgroups.
Введение в Docker
Разбираемся в том, что такое Docker, из каких компонентов состоит и какие технологии контейнеризации использует.