2016-12-04 2 views
9

У меня есть Docker файл как следующее:Как уменьшить размер изображения докеры java/gradle?

FROM openjdk:8 

ADD . /usr/share/app-name-tmp 

WORKDIR /usr/share/app-name-tmp 

RUN ./gradlew build \ 
    mv ./build/libs/app-name*.jar /usr/share/app-name/app-name.jar 

WORKDIR /usr/share/app-name 

RUN rm -rf /usr/share/app-name-tmp 

EXPOSE 8080 

RUN chmod +x ./docker-entry.sh 

ENTRYPOINT [ "./docker-entry.sh" ] 

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

ответ

4

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

Извлеките отдельную инструкцию RUN rm -rf /usr/share/app-name-tmp и включите ее в ту же инструкцию RUN, что и градир, как показано ниже.

RUN ./gradlew build \ 
    mv ./build/libs/app-name*.jar /usr/share/app-name/app-name.jar \ 
    rm -rf /usr/share/app-name-tmp/* 

Таким образом, окончательный Dockerfile будет

FROM openjdk:8 

ADD . /usr/share/app-name-tmp 
WORKDIR /usr/share/app-name-tmp 

RUN ./gradlew build \ 
    mv ./build/libs/app-name*.jar /usr/share/app-name/app-name.jar \ 
    rm -rf /usr/share/app-name-tmp/* 

WORKDIR /usr/share/app-name 

EXPOSE 8080 
RUN chmod +x ./docker-entry.sh 
ENTRYPOINT [ "./docker-entry.sh" ] 

Изображение построено по-прежнему складываются размер из каталога/USR/доли/приложения-имя-TMB.

+0

Базовое изображение может немного способствовать, но это реальный ответ. К сожалению, [Docker не обратился к «вложенным сборкам»] (https://github.com/docker/docker/issues/7115). Как я обычно имел дело с этим, есть отдельные изображения «build» и «runtime» для обработки ограничений Docker. См. [Эту статью] (https://www.fpcomplete.com/blog/2015/12/docker-split-images) для возможного способа решения проблемы. – mkobit

+0

@mkobit теперь вы можете использовать многоэтапные сборки для решения этой проблемы https://docs.docker.com/engine/userguide/eng-image/multistage-build/ –

+1

@ GuidoGarcía хорошая точка! Может быть хорошей возможностью для нового ответа или улучшения этого. – mkobit

1

Кажется, что ваш образ приходит от

FROM openjdk:8

так из

https://github.com/docker-library/openjdk/blob/e6e9cf8b21516ba764189916d35be57486203c95/8-jdk/Dockerfile

и на самом деле в Debian

FROM buildpack-deps:jessie-scm

вам S hould пытаются использовать альпийскую базу

https://github.com/docker-library/openjdk/blob/9a0822673dffd3e5ba66f18a8547aa60faed6d08/8-jdk/alpine/Dockerfile

Я предполагаю, что ваше изображение будет по крайней мере, половина размера

+0

Я знаю о Alpine, но я хочу продолжать использовать изображение openjdk: 8. Это ~ 650 МБ, но мое приложение добавляет около 500 Мбайт больше на этапе сборки ./gradlew. – diugalde

6

Я действительно путает о вашем размере изображения. У меня есть типичные приложения Spring Boot, предлагающие услугу REST, включая встроенный контейнер сервлетов менее 200 МБ! Похоже, что ваши зависимости проектов могут и должны быть оптимизированы.

Docker Изображение

openjdk:8 (243MB сжатый) может быть заменен на один с пониженной Alpine UniX изображение как openjdk:8-jdk-alpine (52MB) в качестве основного изображения, но если вам не нужны возможности компилятора (например, дон не используйте JSP), вы также можете перейти на openjdk:8-jre-alpine (42MB), который включает только время выполнения, посмотрите на Docker Hub. Я использую это для сервисов REST для Spring Spring, работающих отлично.

Java Зависимости

Ява зависимости, необходимые для компиляции и выполнения, должны быть включены, но вы можете иметь неиспользованные зависимости включены:

  • проверить зависимости, текущие зависимости компиляции/времени выполнения действительно используется или может быть удалено или перенесено на тестирование, см. Gradle Java Plugin
  • Некоторые зависимости имеют много транзитивных зависимостей (отображение с использованием gradle dependencies), проверьте наличие unne и исключить их, если они не используются, см. Gradle Dependency Management. Обязательно выполните интеграционные тесты перед окончательным применением, некоторые транзитивные зависимости не являются хорошо документированными, но могут быть важными!
+1

Если я выполняю сборку ./gradlew, итоговая баночка составляет всего 95 МБ, но размер изображения составляет около 1 ГБ. – diugalde

+0

Почему вы используете градир с докеров и что находится в каталогах, которые вы добавляете? Я использую плагин доклеек градиента и добавляю только банку к графическому вызывающему докеру из градиента, а не наоборот –

0

Это контейнер, который вы используете для производства? Если это так, не используйте его для реальной сборки. Сделайте сборку (и тестирование) в другом месте, и как только она будет благословлена, скопируйте только JAR в контейнер для производства Docker.

3

С докером 17.05+ вы можете использовать multi-stage builds.

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

Так что ваш Dockerfile может выглядеть следующим образом:

# 
# first stage (build) 
# 
FROM openjdk:8 as build 

ADD . /usr/share/app-name-tmp 

WORKDIR /usr/share/app-name-tmp 

RUN ./gradlew build && \ 
    mv ./build/libs/app-name*.jar /usr/share/app-name/app-name.jar 

# 
# second stage. use alpine to reduce the image size 
# 
FROM openjdk:8-jre-alpine 

WORKDIR /usr/share/app-name 

COPY --from=build /usr/share/app-name/app-name.jar . 

EXPOSE 8080 

RUN chmod +x ./docker-entry.sh 

ENTRYPOINT [ "./docker-entry.sh" ] 

Таким образом, вы только держать банку и все ненужные файлы, которые не включены в окончательный образ.

+1

Не должно быть 'COPY --from = build', поскольку первый этап называется' build' (а не 'builder')? –

Смежные вопросы