Перейти к основному содержимому

Уменьшить контекст сборки для команды сборки Docker

· 6 мин. чтения

1. Обзор

Контекст сборки Docker состоит из файлов или папок, расположенных по определенному пути или URL-адресу. Во время сборки эти файлы отправляются демону Docker, чтобы образ мог использовать их как файлы.

В этом руководстве мы узнаем о контексте сборки Docker и проблемах, связанных с ним. Мы рассмотрим различные способы уменьшения контекста сборки для создания образа.

2. Понимание контекста сборки Docker

Прежде чем мы приступим к решению этой проблемы, давайте сначала разберемся в контексте сборки Docker и в том, как он работает. Контекст сборки Docker — это набор файлов и каталогов, которые будут доступны для механизма Docker, когда мы запустим сборку docker , и все, что не является частью контекста сборки, не будет доступно для команд в нашем Dockerfile .

В некоторых случаях Docker CLI и Docker Engine могут работать на разных компьютерах. Во время сборки Docker интерфейс командной строки Docker отправляет файлы в механизм Docker для создания образа.

Мы также можем использовать URL-адрес репозитория GIT в качестве контекста сборки. В результате контекст сборки становится содержимым указанного репозитория git.

3. Понимание проблемы

Мы поймем проблемы, связанные с контекстом сборки, при создании образа. Чтобы лучше понять проблему контекста сборки, давайте возьмем пример и создадим образец Dockerfile:

FROM   centos:7
MAINTAINER maintainer@foreach.com
COPY jdk-8u202-linux-x64.rpm /

Чтобы создать образ, нам нужно выполнить следующую команду:

$ docker build -t javaapplication .

Вывод вышеуказанной команды:

Sending build context to Docker daemon  178.4MB
Step 1/3 : FROM centos:7
---> eeb6ee3f44bd
Step 2/3 : MAINTAINER maintainer@foreach.com
---> Using cache
---> 4c798858cf11
Step 3/3 : COPY jdk-8u202-linux-x64.rpm /
---> Using cache
---> 9c58f775bb80
Successfully built 9c58f775bb80
Successfully tagged test:latest

Давайте теперь поместим jdk-8u202-linux-x64.tar.gz размером 186M в тот же каталог, не внося изменений в Dockerfile.

При запуске команды сборки docker мы получим следующий вывод:

Sending build context to Docker daemon  372.5MB
Step 1/3 : FROM centos:7
---> eeb6ee3f44bd
Step 2/3 : MAINTAINER maintainer@foreach.com
---> Using cache
---> 4c798858cf11
Step 3/3 : COPY jdk-8u202-linux-x64.rpm /
---> Using cache
---> 9c58f775bb80
Successfully built 9c58f775bb80
Successfully tagged test:latest

Здесь мы видим, что контекст сборки для демона Docker увеличился с 178,4 МБ до 372,5 МБ , хотя мы не вносили никаких изменений в Dockerfile.

Одним из ключевых моментов контекста сборки Docker является то, что он рекурсивно включает все файлы и папки текущего рабочего каталога и отправляет их демону Docker.

4. Решение с использованием файла . Файл dockerignore

Чтобы уменьшить контекст сборки Docker. Мы можем использовать файл .dockerignore для решения проблемы контекста сборки.

Интерфейс командной строки Docker ищет файл с именем .dockerignore в корневом каталоге контекста, прежде чем отправить его демону Docker. Если файл существует, CLI исключает каталоги и файлы, соответствующие его шаблонам. Это предотвратит ненужную отправку больших файлов или важных каталогов демону Docker.

Здесь мы добавим файл jdk-8u202-linux-x64.tar.gz в файл .dockerignore , чтобы игнорировать его при создании сборки:

$ echo "jdk-8u202-linux-x64.tar.gz" > .dockerignore

Давайте теперь создадим образ Docker:

$ docker build -t foreach  .
Sending build context to Docker daemon 178.4MB
Step 1/3 : FROM centos:7
---> eeb6ee3f44bd

Здесь мы ясно видим, что контекст сборки Docker, отправляемый демону Docker, был уменьшен с 372,5 МБ до 178,4 МБ.

5. Использование создания файла EOF

Мы создадим Dockerfile напрямую, используя команду сборки docker с EOF.

Предположим, что у нас есть следующий Dockerfile:

FROM   centos:7
MAINTAINER maintainer@foreach.com
RUN echo "Welcome to Bealdung"

Чтобы собрать образ для вышеуказанного файла Dockerfile. Мы запускаем команду сборки docker и получаем следующий вывод:

$ docker build -t foreach .
Sending build context to Docker daemon 372.5MB
Step 1/3 : FROM centos:7
---> eeb6ee3f44bd
Step 2/3 : MAINTAINER maintainer@foreach.com
---> Using cache
---> a7088e6a3e53
Step 3/3 : RUN echo "Welcome to Bealdung"
---> Using cache
---> 1fc84e62de75
Successfully built 1fc84e62de75
Successfully tagged foreach:latest

Здесь мы видим, что контекст сборки Docker, отправленный демону Docker, составляет 372,5 МБ . Если мы запустим тот же Dockerfile следующим образом:

$ docker build -t test -<<EOF
FROM centos:7
MAINTAINER maintainer@foreach.com
RUN echo "Welcome to Bealdung"
EOF

Вывод вышеуказанной команды выглядит следующим образом:

Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM centos:7
---> eeb6ee3f44bd
Step 2/3 : MAINTAINER maintainer@foreach.com
---> Using cache
---> a7088e6a3e53
Step 3/3 : RUN echo "Welcome to Bealdung"
---> Running in 6240c486fcb5
Welcome to Bealdung
Removing intermediate container 6240c486fcb5
---> 1fc84e62de75
Successfully built 1fc84e62de75
Successfully tagged foreach:latest

Здесь мы видим, что контекст сборки был уменьшен с 372 МБ до 2,048 КБ. Это решение работает только в тех случаях, когда мы не используем команды COPY и ADD.

6. Оптимизация образов Docker

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

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

6.1. Использование многоэтапных сборок

В многоэтапных сборках мы используем несколько операторов FROM в одном Dockerfile. Каждая инструкция FROM использует другую базу, и каждая инструкция FROM запускает новый этап сборки. Артефакты можно выборочно копировать с одного этапа на другой.

Давайте рассмотрим пример использования многоступенчатости в Dockerfile:

FROM centos:7 as builder
RUN yum -y install maven
COPY spring-boot-application /spring-boot-application
WORKDIR /spring-boot-application/
RUN mvn clean package -Dmaven.test.skip=true
FROM centos:7
RUN yum install -y epel-release \
&& yum install -y maven wget \
&& yum -y install java-1.8.0-openjdk \
&& yum clean all
COPY --from=builder /spring-boot-application/target/spring-boot-application-0.0.1-SNAPSHOT.jar /
CMD ["java -jar ","-c","/spring-boot-application-0.0.1-SNAPSHOT.jar && tail -f /dev/null"]

Здесь, в приведенном выше Dockerfile, мы использовали два оператора From . Сначала мы создали spring-boot-application-0.0.1-SNAPSHOT.jar с помощью команды mvn на первом уровне. Затем мы использовали тот же файл jar во втором слое с помощью команды «COPY –from=builder» . Таким образом, мы можем удалить первый слой и значительно уменьшить размер.

6.2. Уменьшите количество этапов

При создании образа следует обратить внимание на слои, созданные Dockerfile. Команда RUN создает новый уровень для каждого выполнения. Размер изображения можно уменьшить, комбинируя слои.

Как правило, пользователи запускают команду следующим образом:

RUN apt-get -y update
RUN apt-get install -y python

Приведенный выше Dockerfile создаст два слоя. Но объединение обеих команд вместе создаст один слой в финальном изображении:

RUN apt-get -y update && apt-get install -y python

Таким образом, умные комбинации команд могут привести к уменьшению изображения.

6.3. Создание пользовательских базовых изображений

Docker кэширует изображения. Всякий раз, когда у нас есть несколько экземпляров одного и того же слоя, мы должны оптимизировать слои и создать собственное базовое изображение. Время загрузки будет ускорено, а отслеживание станет проще.

7. Заключение

В этом руководстве мы узнали о концепции контекста сборки в Docker. Сначала мы обсудили детали и выполнение контекста сборки Docker.

Затем мы решили проблему увеличения контекста сборки при создании образа Docker с помощью команды сборки docker . Сначала мы изучили варианты использования проблемы, а затем решили их разными способами в Docker.

Наконец, мы рассмотрели различные подходы к оптимизации образа Docker.