Pull to refresh

Comments 31

Я не понимаю эту логику: зачем из gradle, запускать docker. Gradle, как Maven, сам по себе требует изоляции в CI, иначе вы становитесь зависимы от версии стоящей на CI узле (ну или машине разработчика).


На мой взгляд логичный путь это:


  • запуск gradle/maven/ant в специальном сборочном образе. На выходе tgz с приложением, готовым к развороту.
  • запуск docker build с командой распаковки tgz.
а можно пример/подробнее как все это сделать красиво в мавене?

Что сделать в Maven? А то я как-то не понял вопрос.

пример мавен проекта, что красиво складывает проект и депенденси в архив.

Красиво, это не про maven, а по сути такое есть во многих открытых проектах. Например посмотрите проекты на apache.org.

дык о том и речь, с докер плагином можно все более менее красиво оформить. а как вот иначе?

У нас явно разное представление о прекрасном :). Это зависит от того что вы используете в CI. На хабре даже была стать как такие вещи на make делать.

Мда, где то я вдел этого автора ;-)
Тем не менее у этого подхода есть и свои минусы. Товарищъ выше говорит о вполне интересной альтернативе, когда проект собирает только джарники, а дальше они сдаются следующему шагу, который пакует докер или еще чего непотребного делает.
Такой подход должен лучше ложится на современные представления о CI/CD.

Ну да ладно, покумекаю на досуге.

именно. А что в вашем варианте не так? Поменяйте фазу для сборки docker-образа с package на install и получите что вам нужно — фаза package для сборки Jar, а фаза Install для сборки docker-образа. Install это же не только установка jar-файла в репозитарий Maven...


А чтобы прям совсем разные запуски были — разнесите по профилям запуск сборки Jar и сборки Docker файла. Тогда можете остаться на одной фазе package, но в одном случае соберётся jar, а в другом docker

Gradle, как Maven, сам по себе требует изоляции в CI, иначе вы становитесь зависимы от версии стоящей на CI узле (ну или машине разработчика).

gradlew (mvnw)… же…

хотя зависимость от окружения все равно в тяжелых случаях остается.
да и не в тяжелых, те же url'ы до maven-репозитариев (у суровых контор все закрыто)
те же url'ы до maven-репозитариев (у суровых контор все закрыто)

Вопрос не в закрытости, а в скорости. Дело в том, что среднее приложение на java тянет так много при сборке, что лучше ставить кеширующий Artifactory. Это может на порядок увеличивать скорость сборки.
А вот локальный кеш Maven скорее помеха, когда у вас много чего собирается, многими машинами. В среднем этот кеш будет просто лежать мертвым грузом.

gradlew (mvnw)… же…
хотя зависимость от окружения все равно в тяжелых случаях остается.

К тому же замусоривается CI узел, поскольку методов изоляции действий там не так много. Ещё плюсом запуска Gradle в Docker мне видится унификация и примитивность настройки CI узла: все что нужно это docker.

Из своего опыта работы с Jenkins и Teamcity могу сказать, что сборка в докер-контейнерах обычно протекает немного медленнее, а если используются обычные агенты с предустановленными maven и gradle, с правильными настройками очистки/сброса кэша, то особых проблем с сборкой не замечал. Тут уже в зависимости от нужд надо решать, лучшая изоляция или чуть большая скорость. По поводу кеширующего Artifactory — при большом количестве агентов и сборок может быть высокая нагрузка на сеть и в итоге будет потеря в скорости сборки. Если количество сборок небольшое, то Ваш вариант с раздельными сборкой артефакта приложения в контейнере и упаковки его в отдельный образ — отличное решение.
По поводу локальной сборки на машине разработчика — лично мне удобно иметь локально установленный maven и gradle и запускать сборки из ide, локально собирать в отдельном докер-контейнере мне кажется излишним.

Медленее чем что? Чем поднятый Gradle Server? Да есть такое дело. Он действительно после прогрева работает бодрее.
Ещё вариант, что у вас идет запись внутри контейнера, а это всегда медленно (из-за файловой системы). Надо маунтить временные папки (тот ещё гемор, честно говоря, поскольку сначала надо составить список). Либо вести сборку строго в tmpfs. Вот в этом случае скорость будет космической.


По поводу кеширующего Artifactory — при большом количестве агентов и сборок может быть высокая нагрузка на сеть и в итоге будет потеря в скорости сборки.

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

Level 1.
Официальный openjdk приносит с собой 600 МБ (jre — 450 МБ).
* Если на базе дебиана сделать — то итог 737 мб.
* Если на базе алпайна — то 639 мб.
Сильно выйграть не получиться. А это мы ещё апп внутрь не заливали.

Сделать контейнер меньше всегда хочется и приветствуется. Но никогда не понимал попытку сэкономить на спичках.
Как не читаешь на эту тему что-нибудь: так все работают в гуглах, фейсбуках, нетфликсах и у всех 10к+ машин и 100к+ контейнеров. Как дело доходит до практики — 3 сервера и 5 контейнеров :).

Дело не столько в занимаемом месте, сколько во времени скачивания, а значит во времени холодного старта.


Если правильно подойти к проблеме, то можно экономить за счет общих базовых слоев, но надо продумывать CD и вообще цикл жизни контейнера.

Да, из-за скачивания холодный старт может быть на 1-2 секунды дольше. Например, вместо 12 секунд будет 14.

У самого есть такая проблема: оптимизировать по каплям, где всё просто и понятно, когда что-то и так работает нормально. Не смотреть в сторону того, что создаёт 90% проблем потому, что там сложнее и чуть менее понятнее.

Проблема не в самих 2 секундах, а в линейном росте задержки по числу контейнеров. Это концептуальная проблема построения кластеров, которая решатеся, только с помощью bittorrent. Мне приходилось работать над софтом, который должен разворачивать 2000 нод за разумное время. И там все было очень плохо.

Ну, вообще цифры немного другие:
openjdk 8-jdk-alpine 3b1fdb34c52a 10 hours ago 101MB
openjdk 8-jre-alpine 5699ac7295f9 12 hours ago 81.4MB


В 6-7 раз меньший размер образа позволяет запускать агенты сборки с меньшим объемом памяти, экономить место локально, по сравнению с 700~800 Мб — довольно большая разница.

Я смотрел из статьи:
openjdk 8 db77212ffe05 13 days ago 737MB
openjdk jre e956268fd4ed 13 days ago 538MB

Alpine меньше, но не из-за того что «alpine vs debian», т.к. между ними разница в 95 мб
Могу только осторожно предпложить, что не каждый java проект заведётся на этом alpine образе

Думаю что заведется, там скорее всего выкинули docs/examples/tests.

И ещё чего-нибудь из этого списка (конечно, не всем нужен какой-нибудь gtk):
Скрытый текст
— libasound2 (>= 1.0.16)
— libatk1.0-0 (>= 1.12.4)
— libc6 (>= 2.7)
— libcairo2 (>= 1.2.4)
— libfontconfig1 (>= 2.11)
— libfreetype6 (>= 2.2.1)
— libgcc1 (>= 1:4.2)
— libgdk-pixbuf2.0-0 (>= 2.22.0)
— libglib2.0-0 (>= 2.35.9)
— libgtk2.0-0 (>= 2.24.0)
— libpango-1.0-0 (>= 1.22.0)
— libpangocairo-1.0-0 (>= 1.14.0)
— libpangoft2-1.0-0 (>= 1.14.0)
— libstdc++6 (>= 4.1.1)
— libx11-6
— libxext6
— libxi6
— libxml2 (>= 2.7.4)
— libxrender1
— libxslt1.1 (>= 1.1.25)
— libxtst6
— libxxf86vm1

Spring Boot и обычные jar-ники работают нормально, если нужно что-то хитрее — например обычный Tomcat, то тоже проблем по идее не будет.

А кто-нибудь пробовал собирать image c Oracle Server JRE по официальной инструкции Оракла? (см. Oracle blog)
На сколько я понял, готовый имидж скачать нельзя, но в статье есть ссылка (в FAQ) как подключить его в свой образ (Link)
К слову, получается, что использование Oracle JRE никак не нарушает лицензию
Выдержка из блога
Are there any licensing considerations for Oracle Java SE that are unique to Docker?
No. Docker is a containerization platform and there are no unique or special restrictions in the license for use or redistribution as compared to any operating system, virtualization or packaging format. The Oracle JDK is widely used and adopted in the Docker ecosystem.

Поправьте, если не прав…

Почему --memory должен быть в 2 раза больше -Xmx?

Данная рекомендация актуальна, если не используются флаги
-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
В 2 раза больше, потому что при запуске с командой -m 150M докер-демон выделит так же 150 Мб под swap.
https://developers.redhat.com/blog/2017/03/14/java-inside-docker/


Но, в целом, увеличение памяти в 2 раза не всегда спасает, т.к. может быть зарезервировано больше памяти и лучше использовать данные флаги(они доступны с версии Java SE 8u131 и в 9-й версии Java) или комбинации ограничений для докер-контейнера по swap и memory.

Если -m 150m выделит оперативной 150, то почему Xmx должен быть 75? Почему не 140, например?

А где описание хитростей слоев? Где рассказ про слой зависимостей и слой приложения?

Sign up to leave a comment.