Bagaimana cara merakit proyek maven? dan berapa banyak cara untuk mencapainya?

90

Saya baru mengenal Docker, dan tidak tahu bagaimana menjalankan proyek java dengan maven meskipun saya telah membaca banyak dokumen dan mencoba banyak metode.

  1. Haruskah saya membuat gambar menggunakan Dockerfile?
  2. Seperti apa perintahnya saat menjalankan proyek maven di host dengan Dockerfile?
Yashon Lin
sumber

Jawaban:

125

Contoh kerja.

Ini bukan tutorial boot musim semi. Ini adalah jawaban yang diperbarui untuk pertanyaan tentang cara menjalankan build Maven dalam container Docker.

Pertanyaan awalnya diposting 4 tahun yang lalu.

1. Buat aplikasi

Gunakan penginisialisasi pegas untuk membuat aplikasi demo

https://start.spring.io/

masukkan deskripsi gambar di sini

Ekstrak arsip zip secara lokal

2. Buat Dockerfile

#
# Build stage
#
FROM maven:3.6.0-jdk-11-slim AS build
COPY src /home/app/src
COPY pom.xml /home/app
RUN mvn -f /home/app/pom.xml clean package

#
# Package stage
#
FROM openjdk:11-jre-slim
COPY --from=build /home/app/target/demo-0.0.1-SNAPSHOT.jar /usr/local/lib/demo.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/usr/local/lib/demo.jar"]

Catatan

  • Contoh ini menggunakan build multi-tahap . Tahap pertama digunakan untuk membangun kode. Tahap kedua hanya berisi jar yang dibangun dan JRE untuk menjalankannya (perhatikan bagaimana jar disalin antar tahapan).

3. Bangun citra

docker build -t demo .

4. Jalankan image

$ docker run --rm -it demo:latest

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.3.RELEASE)

2019-02-22 17:18:57.835  INFO 1 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication v0.0.1-SNAPSHOT on f4e67677c9a9 with PID 1 (/usr/local/bin/demo.jar started by root in /)
2019-02-22 17:18:57.837  INFO 1 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2019-02-22 17:18:58.294  INFO 1 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 0.711 seconds (JVM running for 1.035)

Misc

Baca dokumentasi hub Docker tentang bagaimana build Maven dapat dioptimalkan untuk menggunakan repositori lokal ke cache jars.

Perbarui (2019-02-07)

Pertanyaan ini sekarang sudah berusia 4 tahun dan pada saat itu bisa dikatakan membangun aplikasi menggunakan Docker telah mengalami perubahan yang signifikan.

Opsi 1: Pembuatan multi-tahap

Gaya baru ini memungkinkan Anda membuat gambar yang lebih ringan yang tidak merangkum alat pembuatan dan kode sumber Anda.

Contoh di sini lagi-lagi menggunakan gambar dasar maven resmi untuk menjalankan tahap pertama pembuatan menggunakan versi Maven yang diinginkan. Bagian kedua dari file menentukan bagaimana toples yang dibangun dirakit menjadi gambar keluaran akhir.

FROM maven:3.5-jdk-8 AS build  
COPY src /usr/src/app/src  
COPY pom.xml /usr/src/app  
RUN mvn -f /usr/src/app/pom.xml clean package

FROM gcr.io/distroless/java  
COPY --from=build /usr/src/app/target/helloworld-1.0.0-SNAPSHOT.jar /usr/app/helloworld-1.0.0-SNAPSHOT.jar  
EXPOSE 8080  
ENTRYPOINT ["java","-jar","/usr/app/helloworld-1.0.0-SNAPSHOT.jar"]  

catatan:

  • Saya menggunakan gambar dasar distroless Google , yang berusaha menyediakan waktu yang cukup untuk aplikasi java.

Opsi 2: Jib

Saya belum pernah menggunakan pendekatan ini tetapi tampaknya layak untuk diselidiki karena memungkinkan Anda membuat gambar tanpa harus membuat hal-hal buruk seperti Dockerfiles :-)

https://github.com/GoogleContainerTools/jib

Proyek ini memiliki plugin Maven yang mengintegrasikan pengemasan kode Anda langsung ke alur kerja Maven Anda.


Jawaban asli (Termasuk untuk kelengkapan, tetapi ditulis berabad-abad yang lalu)

Coba gunakan gambar resmi baru, ada satu untuk Maven

https://registry.hub.docker.com/_/maven/

Image dapat digunakan untuk menjalankan Maven pada waktu build untuk membuat aplikasi yang dikompilasi atau, seperti pada contoh berikut, untuk menjalankan build Maven dalam container.

Contoh 1 - Maven berjalan di dalam wadah

Perintah berikut menjalankan build Maven Anda di dalam container:

docker run -it --rm \
       -v "$(pwd)":/opt/maven \
       -w /opt/maven \
       maven:3.2-jdk-7 \
       mvn clean install

Catatan:

  • Hal yang rapi tentang pendekatan ini adalah bahwa semua perangkat lunak diinstal dan dijalankan di dalam wadah. Hanya perlu buruh pelabuhan di mesin host.
  • Lihat Dockerfile untuk versi ini

Contoh 2 - Gunakan Nexus untuk menyimpan file dalam cache

Jalankan wadah Nexus

docker run -d -p 8081:8081 --name nexus sonatype/nexus

Buat file "settings.xml":

<settings>
  <mirrors>
    <mirror>
      <id>nexus</id>
      <mirrorOf>*</mirrorOf>
      <url>http://nexus:8081/content/groups/public/</url>
    </mirror>
  </mirrors>
</settings>

Sekarang jalankan Maven yang menautkan ke penampung nexus, sehingga dependensi akan di-cache

docker run -it --rm \
       -v "$(pwd)":/opt/maven \
       -w /opt/maven \
       --link nexus:nexus \
       maven:3.2-jdk-7 \
       mvn -s settings.xml clean install

Catatan:

  • Keuntungan menjalankan Nexus di latar belakang adalah repositori pihak ketiga lainnya dapat dikelola melalui URL admin secara transparan ke build Maven yang berjalan di penampung lokal.
Mark O'Connor
sumber
dapatkah ini digunakan untuk menggantikan pusat maven untuk bangunan gradle? sebagaimana dinyatakan dalam support.sonatype.com/entries/… Saya mengganti mavenCentral()dependensi gradle saya dengan maven {url "http://nexus:8081..."dan sekarang baru saja mendapatkan masalah resolusi.
mohamnag
@mohamnag Benar, file "pengaturan" Maven di atas melakukan hal itu, mengarahkan semua permintaan Pusat Maven ke repositori nexus lokal. Anda perlu menguraikan jenis resolusi masalah yang Anda hadapi. Bisa apa saja ... Misalnya, sudahkah Anda menyiapkan tautan Docker, sehingga host "nexus" diselesaikan dengan benar?
Mark O'Connor
Saya ternyata semuanya baik-baik saja, tetapi nexus membutuhkan waktu untuk membangun indeks atau ada hal lain yang menyebabkan masalah. Saya juga mencoba memicu pembaruan indeks oleh karena itu saya tidak yakin kasus mana yang memperbaiki masalah. Namun terima kasih.
mohamnag
Nexus 3 sekarang tersedia sebagai kontainer buruh pelabuhan juga. Gunakan "sonatype / nexus3"
Thorbjørn Ravn Andersen
1
@avandeursen Anda benar bahwa parameter --link tidak digunakan lagi (Jawaban berusia lebih dari 3 tahun). Namun solusi yang lebih tepat (menurut saya) adalah membuat jaringan buruh pelabuhan dan menjalankan kedua kontainer di atasnya. Dengan cara itu Anda dapat memanfaatkan fitur DNS asli di Docker dan terus merujuk ke penampung nexus berdasarkan nama. Akan memperbarui contoh nanti
Mark O'Connor
47

Mungkin ada banyak cara .. Tapi saya implementasikan dengan mengikuti dua cara

Contoh yang diberikan adalah proyek maven.

1. Menggunakan Dockerfile dalam proyek maven

Gunakan struktur file berikut:

Demo
└── src
|    ├── main
|    │   ├── java
|    │       └── org
|    │           └── demo
|    │               └── Application.java
|    │   
|    └── test
|
├──── Dockerfile
├──── pom.xml

Dan perbarui Dockerfile sebagai:

FROM java:8
EXPOSE 8080
ADD /target/demo.jar demo.jar
ENTRYPOINT ["java","-jar","demo.jar"]

Arahkan ke folder proyek dan ketik perintah berikut Anda akan dapat membuat gambar dan menjalankan gambar itu:

$ mvn clean
$ mvn install
$ docker build -f Dockerfile -t springdemo .
$ docker run -p 8080:8080 -t springdemo

Dapatkan video di Spring Boot dengan Docker

2. Menggunakan plugin Maven

Tambahkan plugin maven yang diberikan di pom.xml

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.4.5</version>
        <configuration>
            <imageName>springdocker</imageName>
            <baseImage>java</baseImage>
            <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
            <resources>
                <resource>
                    <targetPath>/</targetPath>
                    <directory>${project.build.directory}</directory>
                    <include>${project.build.finalName}.jar</include>
                </resource>
            </resources>
        </configuration>
    </plugin>

Arahkan ke folder proyek dan ketik perintah berikut, Anda akan dapat membuat gambar dan menjalankan gambar itu:

$ mvn clean package docker:build
$ docker images
$ docker run -p 8080:8080 -t <image name>

Pada contoh pertama kita membuat Dockerfile dan menyediakan base image dan menambahkan jar an so, setelah itu kita akan menjalankan perintah docker untuk membangun image dengan nama tertentu dan kemudian menjalankan image tersebut ..

Sedangkan dalam contoh kedua kita menggunakan maven Plugin di mana kita memberikan baseImagedan imageNamesehingga kita tidak perlu membuat Dockerfile sini .. setelah kemasan proyek maven kita akan mendapatkan gambar buruh pelabuhan dan kita hanya perlu menjalankan gambar yang ..

Riddhi Gohil
sumber
Daripada memodifikasi entrypoint untuk menentukan nama artefak, Anda dapat menggunakan pendekatan seperti di sini: alooma.com/blog/building-dockers - gunakan maven-dependency-plugin untuk menggunakan nama umum. Tidak perlu menempatkan jar berversi di penampung buruh pelabuhan karena penampung itu sendiri berversi.
kboom
14

Sebagai aturan praktis, Anda harus membuat JAR besar menggunakan Maven (JAR yang berisi kode Anda dan semua dependensi).

Kemudian Anda dapat menulis Dockerfile yang sesuai dengan kebutuhan Anda (jika Anda dapat membangun JAR yang besar, Anda hanya memerlukan os dasar, seperti CentOS, dan JVM).

Inilah yang saya gunakan untuk aplikasi Scala (yang berbasis Java).

FROM centos:centos7

# Prerequisites.

RUN yum -y update
RUN yum -y install wget tar

# Oracle Java 7

WORKDIR /opt

RUN wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/7u71-b14/server-jre-7u71-linux-x64.tar.gz
RUN tar xzf server-jre-7u71-linux-x64.tar.gz
RUN rm -rf server-jre-7u71-linux-x64.tar.gz
RUN alternatives --install /usr/bin/java java /opt/jdk1.7.0_71/bin/java 1

# App

USER daemon

# This copies to local fat jar inside the image
ADD /local/path/to/packaged/app/appname.jar /app/appname.jar

# What to run when the container starts
ENTRYPOINT [ "java", "-jar", "/app/appname.jar" ]

# Ports used by the app
EXPOSE 5000

Ini membuat gambar berbasis CentOS dengan Java7. Saat dimulai, aplikasi jar akan dijalankan.

Cara terbaik untuk menerapkannya adalah melalui Docker Registry, ini seperti Github untuk gambar Docker.

Anda dapat membuat gambar seperti ini:

# current dir must contain the Dockerfile
docker build -t username/projectname:tagname .

Anda kemudian dapat mendorong gambar dengan cara ini:

docker push username/projectname # this pushes all tags

Setelah image ada di Docker Registry, Anda dapat menariknya dari mana saja di dunia dan menjalankannya.

Lihat Panduan Pengguna Docker untuk informasi lebih lanjut.

Sesuatu yang perlu diingat :

Anda juga dapat menarik repositori Anda ke dalam gambar dan membuat jar sebagai bagian dari eksekusi penampung, tetapi ini bukan pendekatan yang baik, karena kodenya dapat berubah dan Anda mungkin akan menggunakan versi aplikasi yang berbeda tanpa pemberitahuan.

Membangun toples lemak menghilangkan masalah ini.

Matteo Pacini
sumber
Hai, saya menggunakan contoh Anda di file buruh pelabuhan saya untuk menyalin toples lemak pada gambar tetapi build gagal karena tidak dapat menemukan toples lemak yang diberikan jalur lokal. Apakah itu seperti target / app.jar?
user_mda
Hai, apakah ada cara agar saya dapat mendownload artefak dari nexus saat runtime? Untuk menentukan artefak yang akan diunduh menggunakan properti dan bukan tautan sebenarnya ke jar itu sendiri? Di dockerfile: RUN wget -O {project.build.finalname}.jar Tapi saya ingin mendownload jar di atas dari nexus.
Pramod Setlur
1
Menyertakan FAT JAR ke kode repo lambat bagi saya. Apakah ada cara menggunakan maven untuk membangun citra?
WoLfPwNeR
1
Stoples gemuk juga memiliki masalah, terutama dengan toples bertanda tangan.
Thorbjørn Ravn Andersen
1
Sebagai aturan praktis, jangan pernah menggunakan tabung lemak, paket yang mengandalkan manifes atau file data lain di dalam jar mereka kemungkinan besar akan gagal karena tidak ada cara yang aman untuk menggabungkan data ini. Manifes file dengan jalur yang cocok di dalam konflik jar dan kemenangan pertama atau terakhir (tidak ingat yang mana). Satu-satunya saat Anda harus mempertimbangkan untuk menggunakan tabung lemak adalah jika Anda memiliki sekumpulan ketergantungan yang sangat terbatas dan Anda tahu betul bahwa toples mereka tidak memiliki data manifes yang bertentangan. Jika tidak, tetap aman gunakan toples karena telah dirancang untuk digunakan (misalnya secara terpisah).
PiersyP
3

Inilah kontribusi saya.
Saya tidak akan mencoba membuat daftar semua alat / perpustakaan / plugin yang ada untuk memanfaatkan Docker dengan Maven. Beberapa jawaban telah berhasil.
alih-alih, saya akan fokus pada tipologi aplikasi dan cara Dockerfile.
Dockerfilebenar-benar konsep Docker yang sederhana dan penting (semua gambar yang dikenal / publik bergantung padanya) dan saya pikir mencoba menghindari pemahaman dan penggunaan Dockerfilebelum tentu merupakan cara yang lebih baik untuk masuk ke dunia Docker.

Dockerisasi aplikasi bergantung pada aplikasi itu sendiri dan tujuan yang ingin dicapai

1) Untuk aplikasi yang ingin kita jalankan, jalankan di server Java yang terinstal / mandiri (Tomcat, JBoss, dll ...)

Jalannya lebih sulit dan itu bukan target yang ideal karena itu menambah kompleksitas (kami harus mengelola / memelihara server) dan kurang skalabel serta kurang cepat daripada server tertanam dalam hal build / deploy / undeploy.
Tetapi untuk aplikasi lama, itu mungkin dianggap sebagai langkah pertama.
Secara umum, idenya di sini adalah untuk menentukan gambar Docker untuk server dan untuk menentukan gambar per aplikasi untuk diterapkan.
Gambar buruh pelabuhan untuk aplikasi menghasilkan WAR / EAR yang diharapkan tetapi ini tidak dijalankan sebagai wadah dan gambar untuk aplikasi server menyebarkan komponen yang dihasilkan oleh gambar ini sebagai aplikasi yang diterapkan.
Untuk aplikasi besar (jutaan baris kode) dengan banyak barang warisan, dan sangat sulit untuk bermigrasi ke solusi tertanam boot musim semi penuh, itu benar-benar peningkatan yang bagus.
Saya tidak akan merinci lebih lanjut pendekatan itu karena itu untuk kasus penggunaan kecil Docker tetapi saya ingin mengekspos gagasan keseluruhan dari pendekatan itu karena saya pikir bagi pengembang yang menghadapi kasus-kasus kompleks ini, sangat menyenangkan mengetahui bahwa beberapa pintu dibuka untuk mengintegrasikan Docker.

2) Untuk aplikasi yang menanamkan / bootstrap server itu sendiri (Spring Boot dengan server tertanam: Tomcat, Netty, Jetty ...)

Itu adalah target ideal dengan Docker . Saya menentukan Spring Boot karena itu adalah kerangka kerja yang sangat bagus untuk melakukan itu dan itu juga memiliki tingkat pemeliharaan yang sangat tinggi tetapi secara teori kami dapat menggunakan cara Java lain untuk mencapai itu.
Secara umum, idenya di sini adalah untuk menentukan gambar Docker per aplikasi yang akan diterapkan.
Gambar buruh pelabuhan untuk aplikasi menghasilkan JAR atau sekumpulan file JAR / kelas / konfigurasi dan ini memulai JVM dengan aplikasi (perintah java) saat kita membuat dan memulai penampung dari gambar ini.
Untuk aplikasi baru atau aplikasi yang tidak terlalu rumit untuk dimigrasi, cara itu harus lebih disukai daripada server mandiri karena itu adalah cara standar dan cara paling efisien dalam menggunakan kontainer.
Saya akan merinci pendekatan itu.

Dockerisasi aplikasi maven

1) Tanpa Spring Boot

Idenya adalah membuat fat jar dengan Maven (plugin assembly maven dan bantuan plugin maven shade untuk itu) yang berisi class yang dikompilasi dari aplikasi dan dependensi maven yang diperlukan.
Kemudian kami dapat mengidentifikasi dua kasus:

  • jika aplikasinya adalah aplikasi desktop atau otonom (yang tidak perlu diterapkan di server): kita dapat menentukan seperti CMD/ENTRYPOINTdalam Dockerfileeksekusi java aplikasi:java -cp .:/fooPath/* -jar myJar

  • jika aplikasinya adalah aplikasi server, misalnya Tomcat, idenya sama: untuk mendapatkan jar yang besar dari aplikasi dan menjalankan JVM di CMD/ENTRYPOINT. Tetapi di sini dengan perbedaan penting: kita perlu menyertakan beberapa logika dan pustaka tertentu ( org.apache.tomcat.embedpustaka dan beberapa lainnya) yang memulai server tertanam saat aplikasi utama dimulai.
    Kami memiliki panduan lengkap di situs web heroku .
    Untuk kasus pertama (aplikasi otonom), itu adalah cara yang langsung dan efisien untuk menggunakan Docker.
    Untuk kasus kedua (aplikasi server), yang berfungsi tetapi tidak langsung, mungkin rawan kesalahan dan bukan model yang sangat dapat diperluas karena Anda tidak menempatkan aplikasi Anda dalam kerangka kerangka kerja yang matang seperti Spring Boot yang melakukan banyak hal. hal-hal ini untuk Anda dan juga menyediakan tingkat ekstensi yang tinggi.
    Tetapi itu memiliki keuntungan: Anda memiliki tingkat kebebasan yang tinggi karena Anda menggunakan API Tomcat yang disematkan secara langsung.

2) Dengan Spring Boot

Akhirnya, ini dia.
Itu sederhana, efisien dan didokumentasikan dengan sangat baik.
Sebenarnya ada beberapa pendekatan untuk membuat aplikasi Maven / Spring Boot berjalan di Docker.
Mengekspos semuanya akan lama dan mungkin membosankan.
Pilihan terbaik tergantung pada kebutuhan Anda.
Tapi bagaimanapun caranya, strategi build dari segi layer buruh pelabuhan terlihat sama.
Kami ingin menggunakan build multi-tahap: satu mengandalkan Maven untuk resolusi dependensi dan untuk build dan satu lagi mengandalkan JDK atau JRE untuk memulai aplikasi.

Bangun panggung (gambar Maven):

  • salin pom ke gambar
  • dependensi dan unduhan plugin.
    Tentang itu, mvn dependency:resolve-pluginsdirantai mvn dependency:resolvedapat melakukan pekerjaan itu tetapi tidak selalu.
    Kenapa? Karena plugin ini dan packageeksekusi untuk mengemas tabung lemak mungkin bergantung pada artefak / plugin yang berbeda dan bahkan untuk artefak / plugin yang sama, ini mungkin masih menarik versi yang berbeda. Jadi pendekatan yang lebih aman sementara berpotensi lebih lambat adalah menyelesaikan dependensi dengan mengeksekusi persis mvnperintah yang digunakan untuk mengemas aplikasi (yang akan menarik dependensi yang Anda butuhkan) tetapi dengan melewatkan kompilasi sumber dan dengan menghapus folder target untuk membuat pemrosesan lebih cepat dan untuk mencegah deteksi perubahan lapisan yang tidak diinginkan untuk langkah itu.
  • salin kode sumber ke gambar
  • kemas aplikasi

Run stage (gambar JDK atau JRE):

  • salin toples dari tahap sebelumnya

Berikut dua contoh.

a) Cara sederhana tanpa cache untuk dependensi maven yang diunduh

Dockerfile:

########Maven build stage########
FROM maven:3.6-jdk-11 as maven_build
WORKDIR /app

#copy pom
COPY pom.xml .

#resolve maven dependencies
RUN mvn clean package -Dmaven.test.skip -Dmaven.main.skip -Dspring-boot.repackage.skip && rm -r target/

#copy source
COPY src ./src

# build the app (no dependency download here)
RUN mvn clean package  -Dmaven.test.skip

# split the built app into multiple layers to improve layer rebuild
RUN mkdir -p target/docker-packaging && cd target/docker-packaging && jar -xf ../my-app*.jar

########JRE run stage########
FROM openjdk:11.0-jre
WORKDIR /app

#copy built app layer by layer
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

#run the app
CMD java -cp .:classes:lib/* \
         -Djava.security.egd=file:/dev/./urandom \
         foo.bar.MySpringBootApplication

Kekurangan dari solusi itu? Setiap perubahan di pom.xml berarti membuat ulang seluruh lapisan yang mengunduh dan menyimpan dependensi maven. Hal itu umumnya tidak dapat diterima untuk aplikasi dengan banyak dependensi (dan Spring Boot menarik banyak dependensi), secara keseluruhan jika Anda tidak menggunakan manajer repositori maven selama pembuatan image.

b) Cara yang lebih efisien dengan cache untuk dependensi maven yang diunduh

Pendekatannya di sini sama tetapi unduhan dependensi maven yang di-cache di cache pembuat buruh pelabuhan.
Operasi cache bergantung pada buildkit (api percobaan buruh pelabuhan).
Untuk mengaktifkan buildkit, variabel env DOCKER_BUILDKIT = 1 harus disetel (Anda dapat melakukannya di tempat yang Anda inginkan: .bashrc, baris perintah, file json daemon buruh pelabuhan ...).

Dockerfile:

# syntax=docker/dockerfile:experimental

########Maven build stage########
FROM maven:3.6-jdk-11 as maven_build
WORKDIR /app

#copy pom
COPY pom.xml .

#copy source
COPY src ./src

# build the app (no dependency download here)
RUN --mount=type=cache,target=/root/.m2  mvn clean package -Dmaven.test.skip

# split the built app into multiple layers to improve layer rebuild
RUN mkdir -p target/docker-packaging && cd target/docker-packaging && jar -xf ../my-app*.jar

########JRE run stage########
FROM openjdk:11.0-jre
WORKDIR /app

#copy built app layer by layer
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

#run the app
CMD java -cp .:classes:lib/* \
         -Djava.security.egd=file:/dev/./urandom \
         foo.bar.MySpringBootApplication
davidxxx
sumber