Рубрики
Uncategorized

Оптимизация докера для быстрого сборки и световых изображений

Docker Buildkit можно использовать для оптимизации DockerFiles и добиться значительных достижений в производительности при создании изображений, одновременно уменьшая размер изображения. Теги с Docker, Node, Devops.

Docker автоматически строит изображения, чтение инструкций из DockerFile — текстовый файл, который содержит все команды, в порядке, необходимых для создания данного изображения.

Объяснение выше было извлечено из докера Официальные документы И суммирует то, для чего есть DockerFile. DockerFiles важно работать с тем, что они находятся наш план, наша запись слоев, добавленных к одному образу докера.

Мы узнаем, как воспользоваться Buildkit Особенности, набор улучшений введен на Docker V18.09. Интеграция BuildKit предоставит нам лучшую производительность, управление хранением и безопасность.

Цели

  • уменьшить время сборки;
  • уменьшить размер изображения;
  • Обслуживание усиления;
  • получить воспроизводимость;
  • понять многоступенчатые докера;
  • понять функции Buildkit.

До реквизиты

  • Знание концепций докеров
  • Docker установлен (в настоящее время используя V19.03)
  • Приложение Java (для этого поста я использовал Пример jenkins Maven )

Давайте доберемся до этого!

Простой пример докерафила

Ниже приведен пример неоптимизированного докерафила, содержащего приложение Java. Этот пример был взят из Этот разговор конференции Dockercon . Мы пройдем через несколько оптимизаций, поскольку мы идем.

FROM debian
COPY . /app
RUN apt-get update
RUN apt-get -y install openjdk-11-jdk ssh emacs
CMD ["java", "-jar", "/app/target/my-app-1.0-SNAPSHOT.jar"]

Здесь мы можем спросить себя: Сколько времени нужно, чтобы построить на данном этапе? Чтобы ответить на него, давайте создадим этот докер на нашем локальном компьютерном компьютере и скажу докера, чтобы построить изображение.

# enter your Java app folder
cd simple-java-maven-app-master
# create a Dockerfile
vim Dockerfile
# write content, save and exit
docker pull debian:latest # pull the source image
time docker build --no-cache -t docker-class . # overwrite previous layers
# notice the build time

0,21S User 0,23S Система 0% CPU 1: 55,17 Всего

Вот наш ответ: наша сборка берет 1m55s в этот момент.

Но что, если мы просто включим Buildkit без дополнительных изменений? Есть ли разница?

Включение Buildkit.

Buildkit можно включить с двумя методами:

  1. Установка переменной среды при вызове команды Docker Build, например:
time DOCKER_BUILDKIT=1 docker build --no-cache -t docker-class .
  1. Включение Docker Buildkit по умолчанию, устанавливая конфигурацию демона в /etc/docker/daemon.json Функция правда и перезапустить демону:
{ "features": { "buildkit": true } }

Buildkit Первоначальное воздействие

DOCKER_BUILDKIT=1 docker build --no-cache -t docker-class .

0,54s User 0,93S Система 1% CPU 1: 43,00 Всего

На том же оборудовании сборка заняла ~ 12 секунд меньше, чем раньше. Это означает, что сборка получила ~ 10,43% быстрее почти без усилий.

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

Заказ от наименьшего количества часто меняющихся

Потому что на заказ имеет значение для кэширования, мы переместим Скопировать Команда ближе к концу DockerFile.

FROM debian
RUN apt-get update
RUN apt-get -y install openjdk-11-jdk ssh emacs
RUN COPY . /app
CMD ["java", "-jar", "/app/target/my-app-1.0-SNAPSHOT.jar"]

Избегать «копирования».

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

FROM debian
RUN apt-get update
RUN apt-get -y install openjdk-11-jdk ssh vim
COPY target/my-app-1.0-SNAPSHOT.jar /app
CMD ["java", "-jar", "/app/my-app-1.0-SNAPSHOT.jar"]

Пара APT-Get Update & установка

Это предотвращает использование устаревшего кэша пакета. Кэшируйте их вместе или не кэшируйте их вообще.

FROM debian
RUN apt-get update && \
    apt-get -y install openjdk-11-jdk ssh vim
COPY target/my-app-1.0-SNAPSHOT.jar /app
CMD ["java", "-jar", "/app/my-app-1.0-SNAPSHOT.jar"]

Удалить ненужные зависимости

Не устанавливайте инструменты отладки и редактирования — вы можете установить их позже, когда вы чувствуете, что они нуждаются в них.

FROM debian
RUN apt-get update && \
    apt-get -y install --no-install-recommends \
    openjdk-11-jdk
COPY target/my-app-1.0-SNAPSHOT.jar /app
CMD ["java", "-jar", "/app/my-app-1.0-SNAPSHOT.jar"]

Удалить кеш менеджера пакета

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

FROM debian
RUN apt-get update && \
    apt-get -y install --no-install-recommends \
    openjdk-11-jdk && \
    rm -rf /var/lib/apt/lists/*
COPY target/my-app-1.0-SNAPSHOT.jar /app
CMD ["java", "-jar", "/app/my-app-1.0-SNAPSHOT.jar"]

Используйте официальные изображения, где это возможно

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

FROM openjdk
COPY target/my-app-1.0-SNAPSHOT.jar /app
CMD ["java", "-jar", "/app/my-app-1.0-SNAPSHOT.jar"]

Используйте определенные теги

Не используйте Последние Как это прокат. Это просит непредсказуемые проблемы.

FROM openjdk:8
COPY target/my-app-1.0-SNAPSHOT.jar /app
CMD ["java", "-jar", "/app/my-app-1.0-SNAPSHOT.jar"]

Ищите минимальные ароматы

Вы можете уменьшить размер базового изображения. Выберите самый легкий, который подходит для вашей цели. Ниже короткий OpenJDK Список изображений.

8 634 МБ. openjdk.
8-jre. 443 МБ openjdk.
8-Jre-Slim 204 МБ openjdk.
8-JRE-ALPINE 83 МБ. openjdk.

Построить из источника в последовательной среде

Может быть, вам не нужен весь JDK. Если вы намереваетесь использовать JDK для Maven, вы можете использовать изображение Maven Docker в качестве основы для вашей сборки.

FROM maven:3.6-jdk-8-alpine
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn -e -B package
CMD ["java", "-jar", "/app/my-app-1.0-SNAPSHOT.jar"]

Получить зависимости на отдельном шаге

Команда DockerFile для получения зависимостей может быть кэширована. Кэширование этого шага ускорит наши сборки.

FROM maven:3.6-jdk-8-alpine
WORKDIR /app
COPY pom.xml .
RUN mvn -e -B dependency:resolve
COPY src ./src
RUN mvn -e -B package
CMD ["java", "-jar", "/app/my-app-1.0-SNAPSHOT.jar"]

Многоступенчатые сборки: удалить зависимости сборки

Зачем использовать многоступенчатые сборки?

  • Отделите сборку из среды выполнения
  • СУХОЙ
  • Различные детали на разработке, тестировании, специфической среде
  • Грященные зависимости (параллелизм)
  • наличие платформы-специфических этапов
FROM maven:3.6-jdk-8-alpine AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn -e -B dependency:resolve
COPY src ./src
RUN mvn -e -B package

FROM openjdk:8-jre-alpine
COPY --from=builder /app/target/my-app-1.0-SNAPSHOT.jar /
CMD ["java", "-jar", "/my-app-1.0-SNAPSHOT.jar"]

Пропускной пункт

Если вы создаете наше приложение в этот момент,

time DOCKER_BUILDKIT=1 docker build --no-cache -t docker-class .

0,41S User 0,54S Система 2% CPU 35,656 Всего

Вы заметите, что наше приложение берет ~ 35,66 секунды строить. Это приятное улучшение. Отныне мы сосредоточимся на функциях для более возможных сценариев.

Многоэтапные сборки: разные ароматизаторы изображения

Приведенный ниже DockerFile показывает другой этап для Debian и альпийского изображения.

FROM maven:3.6-jdk-8-alpine AS builder
…
FROM openjdk:8-jre-jessie AS release-jessie
COPY --from=builder /app/target/my-app-1.0-SNAPSHOT.jar /
CMD ["java", "-jar", "/my-app-1.0-SNAPSHOT.jar"]

FROM openjdk:8-jre-alpine AS release-alpine
COPY --from=builder /app/target/my-app-1.0-SNAPSHOT.jar /
CMD ["java", "-jar", "/my-app-1.0-SNAPSHOT.jar"]

Чтобы построить определенное изображение на сцене, мы можем использовать --target Аргумент:

time docker build --no-cache --target release-jessie .

Различные ароматизаторы изображения (сухой/глобальный arg)

ARG flavor=alpine
FROM maven:3.6-jdk-8-alpine AS builder
…
FROM openjdk:8-jre-$flavor AS release
COPY --from=builder /app/target/my-app-1.0-SNAPSHOT.jar /
CMD ["java", "-jar", "/my-app-1.0-SNAPSHOT.jar"]

Arg Команда может контролировать изображение, которое будет построен. В приведенном выше примере мы написали альпийский как вкус по умолчанию, но мы можем пройти --build-arg вкус = <вкус> на Docker Build команда.

time docker build --no-cache --target release --build-arg flavor=jessie .

Параллельность

СООТВЕТСТВЕННОСТЬ важно при создании докеровских изображений, поскольку требуется наибольшее преимущество в доступных потоках CPU. В линейном доке докера все этапы выполняются в последовательности. С Multi-Stophing Builds мы можем быть готовы к меньшим этапам зависимости для их использования.

Buildkit даже приводит к другому бонусу производительности. Если этапы не используются позже в сборке, они напрямую пропущены вместо обработки и выброшены при заканчивании. Это означает, что на этапе представления графика ненужные этапы даже не рассматриваются.

Ниже приведен пример DockerFile, где активы веб-сайта встроены в ресурсы сцена:

FROM maven:3.6-jdk-8-alpine AS builder
…
FROM tiborvass/whalesay AS assets
RUN whalesay "Hello DockerCon!" > out/assets.html

FROM openjdk:8-jre-alpine AS release
COPY --from=builder /app/my-app-1.0-SNAPSHOT.jar /
COPY --from=assets /out /assets
CMD ["java", "-jar", "/my-app-1.0-SNAPSHOT.jar"]

И вот еще один докер, где C и C ++ библиотеки отдельно скомпилированы и принимают участие в строитель этап позже.

FROM maven:3.6-jdk-8-alpine AS builder-base
…

FROM gcc:8-alpine AS builder-someClib
…
RUN git clone … ./configure --prefix=/out && make && make install

FROM g++:8-alpine AS builder-some CPPlib
…
RUN git clone … && cmake …

FROM builder-base AS builder
COPY --from=builder-someClib /out /
COPY --from=builder-someCpplib /out /

Кэш приложения Buildkit.

Buildkit имеет специальную функцию, касающуюся кэша менеджеров пакетов. Вот несколько примеров папок кэша типичных местоположений:

/ var / lib / apt / lists доп
~ / .cache / go-build идти
$ Gopath / pkg / мод Go-модули
~ / .npm. NPM
~ / .cache / pip пипс

Мы можем сравнить этот докер с тем, который представлен в разделе Построить из источника в последовательной среде Отказ Это ранее докерфила не было специального обращения с кэш. Мы можем сделать это с типом горы под названием Cache: - mount = type = cache Отказ

FROM maven:3.6-jdk-8-alpine AS builder
WORKDIR /app
RUN --mount=target=. --mount=type=cache,target /root/.m2 \
    && mvn package -DoutputDirectory=/

FROM openjdk:8-jre-alpine
COPY --from=builder /app/target/my-app-1.0-SNAPSHOT.jar /
CMD ["java", "-jar", "/my-app-1.0-SNAPSHOT.jar"]

Построить секретные объемы

Для смешивания в некоторых функциях безопасности PublyKit, давайте посмотрим, как используются крепления секретного типа, и некоторые случаи они предназначены для. Первый сценарий показывает пример, где нам нужно скрыть файл секретов, как ~/.aws/учетные данные Отказ

FROM 
RUN …
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials,required \
./fetch-assets-from-s3.sh
RUN ./build-scripts.sh

Чтобы построить этот докер, пройдите --secret Аргумент как это:

docker build --secret id=aws,src=~/.aws/credentials

Второй сценарий — это метод, чтобы избежать команд, таких как Скопируйте./Keys/Private.pem/root .ssh/Private.pem , Поскольку мы не хотим, чтобы наши SSH ключей храниться на образе докера после того, как они больше не нужны. Buildkit имеет SSH Тип крепления, чтобы покрыть это:

FROM alpine
RUN apk add --no-cache openssh-client
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
ARG REPO_REF=19ba7bcd9976ef8a9bd086187df19ba7bcd997f2
RUN --mount=type=ssh,required git clone git@github.com:org/repo /work && cd /work && git checkout -b $REPO_REF

Чтобы построить этот докер, вам нужно загрузить свой частный ключ SSH в свой SSH-агент и добавить --ssh = по умолчанию , с по умолчанию Представляя местоположение частного ключа SSH.

eval $(ssh-agent)
ssh-add ~/.ssh/id_rsa # this is the SSH key default location
docker build --ssh=default .

Заключение

Это завершает нашу демонстрацию по использованию Docker Buildkit для оптимизации ваших Dockerfiles и, следовательно, ускорить время сборки ваших изображений.

Эти скорость получают привести к значительному экономии во времени и вычислительной мощности, которые не следует пренебрегать.

Как и Чарльз Дюхигг писал на силу привычки: « Маленькие победы — это последовательное применение небольшого преимущества ». Вы определенно пожнете преимущества, если создаете передовые практики и привычки.

Оригинал: «https://dev.to/jscrambler/dockerfile-optimization-for-fast-builds-and-light-images-3p34»