Pertanyaan Cara membangun kontainer buruh pelabuhan untuk aplikasi java


Apa yang ingin saya lakukan adalah membangun citra buruh pelabuhan untuk aplikasi Java saya, tetapi pertimbangan berikut harus benar untuk sebagian besar bahasa yang dikompilasi.

masalah

Pada server saya membangun saya ingin menghasilkan gambar buruh pelabuhan untuk aplikasi saya sebagai deliverable. Untuk ini saya harus mengkompilasi aplikasi menggunakan beberapa alat membangun (biasanya Gradle, Maven atau Ant) dan kemudian menambahkan file JAR yang dibuat ke gambar buruh pelabuhan. Karena saya ingin gambar buruh pelabuhan untuk mengeksekusi file JAR saya tentu saja akan mulai dari gambar dasar dengan Java yang sudah diinstal.

Ada tiga cara untuk melakukan ini:

biarkan alat membangun mengontrol proses

Dalam hal ini alat build saya mengontrol seluruh proses. Jadi ini mempersiapkan file JAR dan setelah JAR dibuat itu memanggil Docker untuk membuat gambar. Ini berfungsi karena JAR dibuat sebelumnya dan Docker dapat mengabaikan proses pembangunan yang dibutuhkan untuk membuat JAR.

Tapi Dockerfile saya tidak lagi berdiri sendiri. Itu tergantung pada langkah-langkah yang terjadi di luar Docker untuk bekerja. Dalam Dockerfile saya, saya akan memiliki COPY atau ADD pernyataan yang seharusnya menyalin file JAR ke gambar. Pernyataan ini akan gagal ketika toples tidak dibuat sebelumnya. Jadi hanya mengeksekusi Dockerfile mungkin tidak berfungsi. Ini menjadi masalah jika Anda ingin mengintegrasikan dengan layanan yang hanya dibangun menggunakan Dockerfile ini seperti fitur auto-build di DockerHub.

biarkan Docker mengontrol build

Dalam hal ini semua langkah yang diperlukan untuk membuat gambar ditambahkan ke Dockerfile sehingga gambar dapat dibuat dengan hanya mengeksekusi build Docker.

Masalah utama dengan pendekatan ini adalah bahwa tidak ada cara untuk menambahkan ke perintah Dockerfile yang harus dijalankan di luar gambar buruh pelabuhan yang dibuat. Ini berarti saya harus menambahkan kode sumber saya dan alat membangun saya ke gambar buruh pelabuhan dan membangun file JAR saya di dalam gambar. Ini akan menghasilkan gambar saya menjadi lebih besar dari yang seharusnya karena semua file yang ditambahkan yang tidak diperlukan pada saat runtime. Ini juga akan menambahkan lapisan tambahan ke gambar saya.

Edit:

Sebagai @ adrian-mouat menunjukkan jika saya akan menambahkan sumber, membangun aplikasi dan menghapus sumber dalam satu pernyataan RUN saya bisa menghindari menambahkan file dan layer yang tidak perlu ke gambar Docker. Ini berarti membuat beberapa perintah dirantai gila.

dua bangun terpisah

Dalam hal ini kami membagi dua build kami: pertama kami membuat file JAR menggunakan alat build kami dan mengunggahnya ke repositori (Maven atau Ivy repository). Kami kemudian memicu build Docker terpisah yang hanya menambahkan file JAR dari repositori.

kesimpulan

Menurut saya, cara yang lebih baik adalah membiarkan alat membangun mengontrol proses. Ini akan menghasilkan gambar buruh pelabuhan yang bersih dan karena gambar inilah yang ingin kami sampaikan, ini penting. Untuk menghindari Dockerfile yang berpotensi tidak berfungsi, berbohong tentang ini harus dibuat sebagai bagian dari build. Jadi tidak ada yang secara tidak sengaja menggunakannya untuk memulai membangun rusak.

Tetapi ini tidak memungkinkan saya untuk berintegrasi dengan DockerHub.

pertanyaan

Apakah ada cara lain yang saya lewatkan?


32
2017-07-29 09:28


asal


Jawaban:


Hub registri buruh pelabuhan memiliki Gambar Maven yang dapat digunakan untuk membuat kontainer java.

Menggunakan pendekatan ini, mesin build tidak perlu memiliki Java atau Maven pra-instal, Docker mengontrol seluruh proses build.

Contoh

├── Dockerfile
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── org
    │   │       └── demo
    │   │           └── App.java
    │   └── resources
    │       └── log4j.properties
    └── test
        └── java
            └── org
                └── demo
                    └── AppTest.java

Wadah dibangun sebagai berikut:

docker build -t my-maven .

Dan jalankan sebagai berikut:

$ docker run -it --rm my-maven
0    [main] INFO  org.demo.App  - hello world

Dockerfile

FROM maven:3.3-jdk-8-onbuild
CMD ["java","-jar","/usr/src/app/target/demo-1.0-SNAPSHOT-jar-with-dependencies.jar"]

Memperbarui

Jika Anda ingin mengoptimalkan penampung untuk mengecualikan sumber, Anda dapat membuat Dockerfile yang hanya menyertakan jar yang dibangun:

FROM java:8
ADD target/demo-1.0-SNAPSHOT-jar-with-dependencies.jar /opt/demo/demo-1.0-SNAPSHOT-jar-with-dependencies.jar
CMD ["java","-jar","/opt/demo/demo-1.0-SNAPSHOT-jar-with-dependencies.jar"]

Dan buat penampung dalam dua langkah:

docker run -it --rm -w /opt/maven \
   -v $PWD:/opt/maven \
   -v $HOME/.m2:/root/.m2 \
   maven:3.3-jdk-8 \
   mvn clean install

docker build -t my-app .

__

Perbarui (2017-07-27)

Docker sekarang memiliki file membangun multi-tahap kemampuan. Hal ini memungkinkan Docker untuk membangun wadah dengan gambar yang berisi alat-alat build tetapi menghasilkan gambar hanya dengan dependensi runtime.

Contoh berikut menunjukkan konsep ini, perhatikan bagaimana toples disalin dari direktori target fase build pertama

FROM maven:3.3-jdk-8-onbuild 

FROM java:8
COPY --from=0 /usr/src/app/target/demo-1.0-SNAPSHOT.jar /opt/demo.jar
CMD ["java","-jar","/opt/demo.jar"]

21
2017-07-29 20:11



Struktur aplikasi java

Demo
└── src
|    ├── main
|    │   ├── java
|    │   │   └── org
|    │   │       └── demo
|    │   │           └── App.java
|    │   └── resources
|    │       └── application.properties
|    └── test
|         └── java
|               └── org
|                   └── demo
|                         └── App.java  
├──── Dockerfile
├──── pom.xml

Isi Dockerfile

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

Perintah untuk membangun dan menjalankan gambar

  • Pergi ke direktori proyek. Katakanlah D: / Demo
$ cd D/demo
$ mvn clean install
$ docker build demo .
$ docker run -p 8080:8080 -t demo

Periksa apakah penampung sedang berjalan atau tidak

$ docker ps

Outputnya akan

CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                    NAMES
55c11a464f5a        demo1               "java -jar demo.jar"   21 seconds ago      Up About a minute   0.0.0.0:8080->8080/tcp   cranky_mayer

4
2018-04-01 12:25



Beberapa hal:

  • Jika Anda menghapus file dalam instruksi yang sama yang Anda tambahkan, mereka tidak akan memakan ruang di dalam gambar. Jika Anda melihat beberapa Dockerfiles untuk gambar resmi, Anda akan melihat mereka mengunduh sumber, membuatnya, dan menghapus semuanya dalam langkah yang sama (mis. https://github.com/docker-library/python/blob/0fa3202789648132971160f686f5a37595108f44/3.5/slim/Dockerfile). Ini berarti Anda perlu melakukan beberapa senam yang mengganggu, tetapi itu sangat bisa dilakukan.

  • Saya tidak melihat masalah dengan dua Dockerfiles yang terpisah. Yang menyenangkan tentang ini adalah Anda bisa menggunakan JRE daripada JDK untuk menjadi tuan rumah guci Anda.


1
2017-07-29 11:23



Cara termudah adalah dengan biarkan alat membangun mengontrol proses. Jika tidak, Anda harus memelihara file build alat build Anda (seperti pom.xml untuk Maven atau build.gradle untuk Gradle) serta a Dockerfile.

Cara mudah untuk membangun kontainer Docker untuk aplikasi Java Anda adalah menggunakan Jib, yang tersedia sebagai Maven dan Gradle plugin.

Misalnya, jika Anda menggunakan Maven dan ingin membangun penampung Anda ke daemon Docker yang sedang berjalan, Anda bisa menjalankan perintah yang satu ini:

mvn compile com.google.cloud.tools:jib-maven-plugin:0.9.2:dockerBuild

Anda juga bisa membangun langsung ke registri Docker dengan Jib tanpa perlu menginstal docker, jalankan daemon Docker (yang membutuhkan hak akses root), atau tulis a Dockerfile. Ini juga lebih cepat dan membangun gambar secara reproduktif.

Lihat lebih banyak tentang Jib di repo Github-nya: https://github.com/GoogleContainerTools/jib


1
2017-07-09 13:01



ada penggunaan alternatif untuk menjalankan jar atau paket perang

  • tambahkan guci ke dalam gambar.
  • mengatur heapsize untuk java
  • jalankan perintah jar melalui entrypoint

contoh dockerfile

FROM base
ADD sample.jar renamed.jar
ENV HEAP_SIZE 256m
ENTRYPOINT exec java -Xms$HEAP_SIZE -Xmx$HEAP_SIZE -jar renamed.jar

di samping contoh penyebaran paket di tomcat

FROM tomcat7
ADD sample.war ${CATALINA_HOME}/webapps/ROOT.war
CMD ${CATALINA_HOME}/bin/catalina.sh run

Membuat dockerfiles sebagai gambar

cp tomcat.dockerfile /workingdir/Dockerfile
docker build -t name /workingdir/Dockerfile .

Daftar gambar

docker images

Gunakan gambar untuk membuat penampung

docker run --name cont_name --extra-vars var1=val1 var2=val2 imagename

0
2017-12-26 22:09



Sini Saya menggambarkan bagaimana saya melakukannya di lingkungan pengembangan saya.

  • Bangun perang / guci secara lokal dengan Maven
  • Salin ke folder Docker lokal
  • Menjalankan Plugin Intellij Docker yang menciptakan gambar buruh pelabuhan yang berisi perang / guci, menjalankan server aplikasi dan menyebarkannya di server Docker yang jauh

Semoga itu membantu.


0
2018-01-29 10:04



Kami menggunakan Spotify Docker Maven Plugin untuk sementara. Plugin memungkinkan Anda untuk mengikat Docker membangunnya ke fase siklus hidup Maven.

Sebuah contoh: Jalankan Docker membangun setelah pengemasan (fase: paket) aplikasi Anda dengan mengkonfigurasi plugin untuk menambahkan aplikasi yang dibangun sebagai sumber daya untuk membangun konteks Docker. Dalam tahap penerapan jalankan tujuan dorong Docker untuk mendorong gambar Docker Anda ke registri. Ini dapat berjalan di samping plugin penyebaran normal, yang menerbitkan artefak ke dalam repositori seperti Nexus.

Kemudian, kami membaginya menjadi dua pekerjaan terpisah di server CI. Karena Docker hanyalah salah satu cara untuk menjalankan aplikasi Anda (kadang-kadang kita membutuhkan aplikasi yang dirilis pada lingkungan yang berbeda tidak hanya Docker), build Maven tidak boleh bergantung pada Docker.

Jadi pekerjaan pertama merilis aplikasi di Nexus (melalui penyebaran Maven). Pekerjaan kedua (yang dapat menjadi ketergantungan hilir pekerjaan pertama) mengunduh artifak rilis terbaru, melakukan pembuatan Docker dan mendorong gambar ke registri. Untuk mengunduh rilis terbaru kami menggunakan Versi Plugin Maven (versi: gunakan-rilis terbaru) serta Maven Ketergantungan Plugin (ketergantungan: dapatkan dan ketergantungan: copy).

Pekerjaan kedua juga dapat dimulai untuk versi tertentu dari aplikasi untuk (kembali) membangun gambar Docker untuk rilis yang lebih lama. Selain itu Anda dapat menggunakan membangun pipa (pada Jenkins), yang mengeksekusi kedua pekerjaan dan melewati versi rilis atau artefak rilis ke build Docker.


0
2017-07-27 18:33