İşte benim katkım.
Maven ile Docker'dan yararlanmak için var olan tüm araçları / kitaplıkları / eklentileri listelemeye çalışmayacağım. Bazı cevaplar bunu zaten yaptı.
Bunun yerine, uygulama tipolojisine ve Dockerfile yoluna odaklanacağım.
Dockerfile
gerçekten basit ve önemli bir Docker kavramıdır (bilinen tüm / genel görüntüler buna dayanır) ve Dockerfile
s'yi anlamaktan ve kullanmaktan kaçınmaya çalışmanın Docker dünyasına girmenin daha iyi bir yolu olmadığını düşünüyorum .
Bir uygulamayı dockerize etmek, uygulamanın kendisine ve ulaşma hedefine bağlıdır
1) Yüklü / bağımsız Java sunucusunda (Tomcat, JBoss, vb.) Çalıştırmak üzere devam etmek istediğimiz uygulamalar için
Yol daha zordur ve bu ideal hedef değildir çünkü bu karmaşıklık ekler (sunucuyu yönetmemiz / sürdürmemiz gerekir) ve oluşturma / dağıtma / dağıtma açısından gömülü sunuculardan daha az ölçeklenebilir ve daha az hızlıdır.
Ancak eski uygulamalar için bu bir ilk adım olarak kabul edilebilir.
Genel olarak buradaki fikir, sunucu için bir Docker görüntüsü tanımlamak ve dağıtılacak uygulama başına bir görüntü tanımlamaktır.
Uygulamalar için docker görüntüleri beklenen WAR / EAR'ı üretir ancak bunlar kapsayıcı olarak yürütülmez ve sunucu uygulamasının görüntüsü, bu görüntüler tarafından üretilen bileşenleri konuşlandırılmış uygulamalar olarak dağıtır.
Çok sayıda eski malzemeye sahip devasa uygulamalar (milyonlarca satır kod) için ve tam yay önyüklemeli gömülü bir çözüme geçmek çok zor, bu gerçekten güzel bir gelişme.
Bu yaklaşımı daha fazla detaylandırmayacağım, çünkü bu Docker'ın küçük kullanım durumları içindir, ancak bu yaklaşımın genel fikrini ortaya çıkarmak istedim çünkü bu karmaşık durumlarla karşılaşan geliştiriciler için bazı kapıların açıldığını bilmek harika. Docker'ı entegre edin.
2) Sunucunun kendisini gömen / önyükleyen uygulamalar için (Sunucuya gömülü Spring Boot: Tomcat, Netty, Jetty ...)
Docker ile ideal hedef budur . Spring Boot'u belirttim çünkü bunu yapmak için gerçekten güzel bir çerçeve ve aynı zamanda çok yüksek bir sürdürülebilirlik seviyesi var ama teorik olarak bunu başarmak için başka herhangi bir Java yolunu kullanabiliriz.
Genel olarak buradaki fikir, dağıtılacak uygulama başına bir Docker görüntüsü tanımlamaktır.
Uygulamalar için docker görüntüleri bir JAR veya bir dizi JAR / sınıf / yapılandırma dosyası üretir ve bunlar, bu görüntülerden bir konteyner oluşturup başlattığımızda uygulama (java komutu) ile bir JVM başlatır.
Taşınması çok karmaşık olmayan yeni uygulamalar veya uygulamalar için, bu yolun bağımsız sunuculara göre tercih edilmesi gerekir çünkü bu, kapsayıcıları kullanmanın standart yolu ve en verimli yoludur.
Bu yaklaşımı detaylandıracağım.
Bir maven uygulamasını dockerize etme
1) Yaylı Körüksüz
Buradaki fikir, uygulamanın hem derlenmiş sınıflarını hem de gerekli maven bağımlılıklarını içeren Maven (bunun için maven montaj eklentisi ve bunun için maven gölge eklentisi yardımı) ile bir şişman kavanoz oluşturmaktır.
Sonra iki durumu belirleyebiliriz:
Uygulama bir masaüstü ya da (bir sunucu üzerinde konuşlandırılacak gerekmez) özerk uygulama ise: biz belirtebilirsiniz CMD/ENTRYPOINT
içinde Dockerfile
başvurunun java yürütülmesi:java -cp .:/fooPath/* -jar myJar
Uygulama bir sunucu uygulamasıysa, örneğin Tomcat, fikir aynıdır: uygulamanın dolgun bir kavanozunu almak ve bir JVM'yi CMD/ENTRYPOINT
. Ancak burada önemli bir farkla: org.apache.tomcat.embed
Ana uygulama başlatıldığında katıştırılmış sunucuyu başlatan bazı mantık ve belirli kitaplıkları ( kitaplıklar ve diğerleri) eklememiz gerekir. Heroku web sitesinde
kapsamlı bir rehberimiz var .
İlk durum (otonom uygulama) için bu, Docker'ı kullanmanın düz ve verimli bir yoludur.
Çalışan ancak düz olmayan ikinci durum (sunucu uygulaması) için, hataya açık olabilir ve çok genişletilebilir bir model değildir çünkü uygulamanızı Spring Boot gibi olgun bir çerçeve çerçevesine yerleştirmezsiniz. bunların sizin için ve ayrıca yüksek düzeyde bir uzantı sağlar.
Ancak bunun bir avantajı var: Doğrudan gömülü Tomcat API'sini kullandığınız için yüksek düzeyde bir özgürlüğe sahipsiniz.
2) Yaylı Körüklü
Sonunda, işte başlıyoruz.
Bu hem basit, etkili hem de çok iyi belgelenmiştir.
Docker üzerinde çalıştırmak üzere bir Maven / Spring Boot uygulaması yapmak için gerçekten birkaç yaklaşım vardır.
Hepsini açığa çıkarmak uzun ve belki de sıkıcı olurdu.
En iyi seçim, ihtiyacınıza bağlıdır.
Ancak, yol ne olursa olsun, docker katmanları açısından derleme stratejisi aynı görünüyor.
Çok aşamalı bir yapı kullanmak istiyoruz: biri bağımlılık çözümü ve derleme için Maven'e, diğeri ise uygulamayı başlatmak için JDK veya JRE'ye güveniyor.
Oluşturma aşaması (Maven görüntüsü):
- pom görüntüye kopyala
- bağımlılıklar ve eklenti indirmeleri.
O konuda, mvn dependency:resolve-plugins
zincirlenmiş mvn dependency:resolve
daima işi ancak yapabilir.
Neden ? Bu eklentiler ve package
şişman kavanozu paketlemek için yürütme, farklı yapılara / eklentilere ve hatta aynı yapıya / eklentiye dayanabileceğinden, bunlar yine de farklı bir sürümü çekebilir. Bu nedenle, potansiyel olarak daha yavaşken daha güvenli bir yaklaşım mvn
, uygulamayı paketlemek için kullanılan komutu tam olarak çalıştırarak (tam olarak ihtiyacınız olan bağımlılıkları çekecektir), ancak kaynak derlemeyi atlayarak ve işlemi daha hızlı hale getirmek için hedef klasörü silerek bağımlılıkları çözmektir. bu adım için istenmeyen katman değişikliği algılamasını önlemek.
- kaynak kodu resme kopyala
- uygulamayı paketlemek
Çalıştırma aşaması (JDK veya JRE görüntüsü):
- önceki aşamadaki kavanozu kopyala
İşte iki örnek.
a) İndirilen maven bağımlılıkları için önbelleksiz basit bir yol
Dockerfile:
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/* \
-Djava.security.egd=file:/dev/./urandom \
foo.bar.MySpringBootApplication
Bu çözümün dezavantajı? Pom.xml'deki herhangi bir değişiklik, maven bağımlılıklarını indiren ve depolayan tüm katmanı yeniden oluşturduğu anlamına gelir. Genel olarak, görüntü oluşturma sırasında bir maven depo yöneticisi kullanmazsanız, birçok bağımlılığı olan uygulamalar için (ve Spring Boot birçok bağımlılığı çeker) genellikle kabul edilemez.
b) İndirilen maven bağımlılıkları için önbellek ile daha verimli bir yol
Yaklaşım burada aynıdır, ancak docker builder önbelleğinde önbelleğe alınan maven bağımlılıkları indirmeleri.
Önbellek işlemi, buildkit'e (docker'ın deneysel API'si) dayanır.
Buildkit'i etkinleştirmek için, env değişkeni DOCKER_BUILDKIT = 1 ayarlanmalıdır (bunu istediğiniz yerde yapabilirsiniz: .bashrc, komut satırı, docker daemon json dosyası ...).
Dockerfile:
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()
benim gradle bağımlılıklarımaven {url "http://nexus:8081..."
ve şimdi sadece çözünürlük sorunları alıyorsanız.