Ось мій внесок.
Я не буду намагатись перерахувати всі інструменти / бібліотеки / плагіни, які існують для того, щоб скористатися перевагами Docker with Maven. Деякі відповіді це вже зробили.
замість цього я зупинюсь на типології додатків та способі Dockerfile.
Dockerfile
насправді є простою та важливою концепцією Docker (усі відомі / загальнодоступні зображення покладаються на це), і я думаю, що спроба уникнути розуміння та використання Dockerfile
s - не обов'язково кращий спосіб увійти у світ Docker.
Докеризація програми залежить від самої програми та її мети
1) Для програм, які ми хочемо продовжувати, запускати їх на встановленому / автономному сервері Java (Tomcat, JBoss тощо ...)
Дорога складніша, і це не є ідеальною метою, оскільки це додає складності (нам доводиться керувати / підтримувати сервер), а також воно менш масштабоване і менш швидке, ніж вбудовані сервери з точки зору складання / розгортання / розкладання.
Але для застарілих додатків це може розглядатися як перший крок.
Як правило, ідея тут полягає у визначенні образу Docker для сервера та у визначенні образу для кожної програми для розгортання.
Зображення докера для програм створюють очікувані WAR / EAR, але вони не виконуються як контейнер, а образ для серверної програми розгортає компоненти, вироблені цими зображеннями, як розгорнуті програми.
Для величезних додатків (мільйони рядків кодів) з великою кількістю застарілих матеріалів, і так важко перейти на повноцінне вбудоване рішення для весняного завантаження, це справді приємне поліпшення.
Я не буду детально описувати цей підхід, оскільки це стосується незначних випадків використання Docker, але я хотів викласти загальну ідею цього підходу, оскільки я думаю, що для розробників, які стикаються з цими складними кейсами, чудово знати, що деякі двері відкриті для інтегрувати Docker.
2) Для додатків, які самі вбудовують / завантажують сервер (Spring Boot із вбудованим сервером: Tomcat, Netty, Jetty ...)
Це ідеальна мета для Docker . Я вказав Spring Boot, тому що це дійсно приємний фреймворк, який також має дуже високий рівень ремонтопридатності, але теоретично для досягнення цього ми могли б використовувати будь-який інший спосіб Java.
Як правило, ідея тут полягає у визначенні образу Docker для кожної програми для розгортання.
Зображення докера для програм створюють JAR або набір файлів JAR / класів / конфігурації, і вони запускають JVM за допомогою програми (команда java), коли ми створюємо та запускаємо контейнер з цих зображень.
Для нових програм або додатків, не надто складних для міграції, такий спосіб слід віддавати перевагу автономним серверам, оскільки це стандартний спосіб і найбільш ефективний спосіб використання контейнерів.
Я детально розкажу цей підхід.
Докеризація програми maven
1) Без весняного завантаження
Ідея полягає в тому, щоб створити жирову банку за допомогою Maven (допоміжний модуль maven та плагін maven для цього), який містить як складені класи програми, так і необхідні залежності maven.
Тоді ми можемо виділити два випадки:
якщо програма є настільною або автономною програмою (яку не потрібно розгортати на сервері): ми можемо вказати, як CMD/ENTRYPOINT
під час Dockerfile
виконання програми Java:java -cp .:/fooPath/* -jar myJar
якщо додаток є серверним додатком, наприклад Tomcat, ідея та ж: отримати жирний банку програми та запустити JVM в CMD/ENTRYPOINT
. Але тут є важлива відмінність: нам потрібно включити деяку логіку та конкретні бібліотеки ( org.apache.tomcat.embed
бібліотеки та деякі інші), яка запускає вбудований сервер при запуску основної програми.
У нас є вичерпний посібник,
але це має перевагу: ви маєте високий рівень свободи, оскільки використовуєте безпосередньо вбудований API Tomcat. на веб-сайті heroku .
Для першого випадку (автономне додаток) це прямий та ефективний спосіб використання Docker.
У другому випадку (серверний додаток), який працює, але це не прямо, може бути схильним до помилок і не дуже розширюваною моделлю, оскільки ви не розміщуєте свою програму в рамках зрілого фреймворку, такого як Spring Boot, який робить багато цих речей для вас, а також забезпечує високий рівень розширення.
2) З весняним завантаженням
Нарешті, ось і ми.
Це і просто, і ефективно, і дуже добре задокументовано.
Існує кілька підходів до створення програми Maven / Spring Boot для запуску на Docker.
Викриття всіх їх було б довгим і, можливо, нудним.
Найкращий вибір залежить від ваших потреб.
Але як би там не було, стратегія побудови з точки зору докер-шарів виглядає однаково.
Ми хочемо використовувати багатоступеневу збірку: одна, яка покладається на Maven для вирішення залежностей та для збірки, а інша - на JDK або JRE для запуску програми.
Етап збірки (зображення Maven):
- пом копію на зображення
- залежності та завантаження плагінів -.
Про те, mvn dependency:resolve-plugins
прикутий mvn dependency:resolve
може виконувати роботу, але не завжди.
Чому? Оскільки ці плагіни та package
виконання пакувальника жирової банки можуть покладатися на різні артефакти / плагіни і навіть для одного артефакту / плагіна, вони все одно можуть використовувати іншу версію. Отже, більш безпечним підходом, хоча й потенційно повільнішим, є розв’язання залежностей, виконуючи саме mvn
команду, яка використовується для упаковки програми (яка витягуватиме саме ті залежності, які вам потрібні), але пропускаючи компіляцію джерела та видаляючи цільову папку, щоб пришвидшити обробку та запобігти виявленню небажаних змін шару для цього кроку.
- копія вихідного коду на зображення
- упакуйте програму
Етап запуску (зображення JDK або JRE):
- скопіюйте банку з попереднього етапу
Ось два приклади.
а) Простий спосіб без кешу для завантажених залежностей maven
Файл Docker:
FROM maven:3.6-jdk-11 as maven_build
WORKDIR /app
COPY pom.xml .
RUN mvn clean package -Dmaven.test.skip -Dmaven.main.skip -Dspring-boot.repackage.skip && rm -r target/
COPY src ./src
RUN mvn clean package -Dmaven.test.skip
RUN mkdir -p target/docker-packaging && cd target/docker-packaging && jar -xf ../my-app*.jar
FROM openjdk:11.0-jre
WORKDIR /app
ARG DOCKER_PACKAGING_DIR=/app/target/docker-packaging
COPY --from=maven_build ${DOCKER_PACKAGING_DIR}/BOOT-INF/lib /app/lib
COPY --from=maven_build ${DOCKER_PACKAGING_DIR}/BOOT-INF/classes /app/classes
COPY --from=maven_build ${DOCKER_PACKAGING_DIR}/META-INF /app/META-INF
CMD java -cp .:classes:lib
Недолік цього рішення? Будь-які зміни у pom.xml означають повторне створення цілого шару, який завантажує та зберігає залежності maven. Це, як правило, неприйнятно для програм із великою кількістю залежностей (а Spring Boot тягне багато залежностей), загалом, якщо ви не використовуєте менеджер сховищ maven під час побудови зображення.
б) Більш ефективний спосіб з кешем для завантажених залежностей maven
Тут підхід такий самий, але завантаження залежностей maven, які кешуються в кеші конструктора докерів.
Операція кешування спирається на buildkit (експериментальний api docker).
Щоб увімкнути buildkit, потрібно встановити змінну en DOCKER_BUILDKIT = 1 (ви можете зробити це там, де хочете: .bashrc, командний рядок, файл json демона docker ...).
Файл Docker:
FROM maven:3.6-jdk-11 as maven_build
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN --mount=type=cache,target=/root/.m2 mvn clean package -Dmaven.test.skip
RUN mkdir -p target/docker-packaging && cd target/docker-packaging && jar -xf ../my-app*.jar
FROM openjdk:11.0-jre
WORKDIR /app
ARG DOCKER_PACKAGING_DIR=/app/target/docker-packaging
COPY --from=maven_build ${DOCKER_PACKAGING_DIR}/BOOT-INF/lib /app/lib
COPY --from=maven_build ${DOCKER_PACKAGING_DIR}/BOOT-INF/classes /app/classes
COPY --from=maven_build ${DOCKER_PACKAGING_DIR}/META-INF /app/META-INF
CMD java -cp .:classes:lib
mavenCentral()
у своїх залежностях gradle наmaven {url "http://nexus:8081..."
і зараз просто отримую проблеми з вирішенням.