Membuat Imej Docker dengan Spring Boot

1. Pengenalan

Oleh kerana lebih banyak organisasi bergerak ke arah kontena dan pelayan maya, Docker menjadi bahagian yang lebih penting dalam aliran kerja pengembangan perisian. Untuk itu, salah satu ciri baru yang hebat dalam Spring Boot 2.3 adalah keupayaan untuk membuat gambar Docker untuk aplikasi Spring Boot dengan mudah.

Dalam tutorial ini, kita akan melihat cara membuat gambar Docker untuk aplikasi Spring Boot.

2. Binaan Docker Tradisional

Kaedah tradisional untuk membina gambar Docker dengan Spring Boot adalah menggunakan Dockerfile. Berikut adalah contoh mudah:

FROM openjdk:8-jdk-alpine EXPOSE 8080 ARG JAR_FILE=target/demo-app-1.0.0.jar ADD ${JAR_FILE} app.jar ENTRYPOINT ["java","-jar","/app.jar"]

Kita kemudian boleh menggunakan perintah build docker untuk membuat gambar Docker. Ini berfungsi dengan baik untuk kebanyakan aplikasi, tetapi terdapat beberapa kekurangan.

Pertama, kita menggunakan balang lemak yang dibuat oleh Spring Boot. Ini boleh mempengaruhi masa permulaan, terutama di persekitaran yang terkontena . Kami dapat menjimatkan masa permulaan dengan menambahkan kandungan fail jar yang meletup.

Kedua, gambar Docker dibina secara berlapis. Sifat tempayan lemak Spring Boot menyebabkan semua kod aplikasi dan perpustakaan pihak ketiga dimasukkan ke dalam satu lapisan. Ini bermaksud walaupun hanya satu baris kod yang berubah, keseluruhan lapisan harus dibina semula .

Dengan meletupkan balang sebelum membina, kod aplikasi dan perpustakaan pihak ketiga masing-masing mendapat lapisan masing-masing. Ini membolehkan kita memanfaatkan mekanisme cache Docker. Sekarang, apabila satu baris kod diubah, hanya lapisan yang sesuai yang perlu dibina semula.

Dengan ini, mari kita lihat bagaimana Spring Boot telah meningkatkan proses pembuatan gambar Docker.

3. Bahan binaan

Buildpacks adalah alat yang menyediakan kebergantungan kerangka dan aplikasi .

Sebagai contoh, dengan menggunakan balang lemak Spring Boot, buildpack akan menyediakan jangka masa Java untuk kita. Ini membolehkan kita melangkau Dockerfile dan mendapatkan gambar Docker yang masuk akal secara automatik.

Spring Boot merangkumi sokongan Maven dan Gradle untuk buildpacks. Sebagai contoh, membina dengan Maven, kita akan menjalankan perintah:

./mvnw spring-boot:build-image

Mari lihat beberapa output yang berkaitan untuk melihat apa yang berlaku:

[INFO] Building jar: target/demo-0.0.1-SNAPSHOT.jar ... [INFO] Building image 'docker.io/library/demo:0.0.1-SNAPSHOT' ... [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 100% ... [INFO] [creator] ===> DETECTING [INFO] [creator] 5 of 15 buildpacks participating [INFO] [creator] paketo-buildpacks/bellsoft-liberica 2.8.1 [INFO] [creator] paketo-buildpacks/executable-jar 1.2.8 [INFO] [creator] paketo-buildpacks/apache-tomcat 1.3.1 [INFO] [creator] paketo-buildpacks/dist-zip 1.3.6 [INFO] [creator] paketo-buildpacks/spring-boot 1.9.1 ... [INFO] Successfully built image 'docker.io/library/demo:0.0.1-SNAPSHOT' [INFO] Total time: 44.796 s

Baris pertama menunjukkan bahawa kami membina balang lemak standard kami, sama seperti pakej maven biasa.

Baris seterusnya memulakan pembinaan gambar Docker. Sejurus selepas itu, kita melihat binaan menarik di pembangun Packeto.

Packeto adalah pelaksanaan buildpacks asli cloud. Ia berfungsi menganalisis projek kami dan menentukan kerangka kerja dan perpustakaan yang diperlukan . Dalam kes kami, ini menentukan bahawa kami mempunyai projek Spring Boot dan menambah buildpacks yang diperlukan.

Akhirnya, kita melihat gambar Docker yang dihasilkan dan jumlah masa pembinaan. Perhatikan bagaimana pertama kali kita membina, kita menghabiskan banyak masa untuk memuat turun buildpacks dan membuat lapisan yang berbeza.

Salah satu ciri buildpacks yang hebat ialah imej Docker mempunyai pelbagai lapisan. Oleh itu, jika kita hanya menukar kod aplikasi kita, binaan seterusnya akan lebih cepat:

... [INFO] [creator] Reusing layer 'paketo-buildpacks/executable-jar:class-path' [INFO] [creator] Reusing layer 'paketo-buildpacks/spring-boot:web-application-type' ... [INFO] Successfully built image 'docker.io/library/demo:0.0.1-SNAPSHOT' ... [INFO] Total time: 10.591 s

4. balang berlapis

Dalam beberapa kes, kami mungkin lebih suka tidak menggunakan buildpacks - mungkin infrastruktur kami sudah terikat dengan alat lain, atau kami sudah memiliki Dockerfiles tersuai yang ingin kami gunakan semula.

Atas sebab-sebab ini, Spring Boot juga menyokong pembinaan gambar Docker menggunakan balang berlapis . Untuk memahami bagaimana ia berfungsi, mari kita lihat susun atur balang lemak Spring Boot biasa:

org/ springframework/ boot/ loader/ ... BOOT-INF/ classes/ ... lib/ ...

Botol lemak terdiri daripada 3 bidang utama:

  • Kelas bootstrap diperlukan untuk melancarkan aplikasi Spring
  • Kod permohonan
  • Perpustakaan pihak ke-3

Dengan balang berlapis, strukturnya kelihatan serupa, tetapi kami mendapat fail layer.idx baru yang memetakan setiap direktori dalam balang lemak ke lapisan:

- "dependencies": - "BOOT-INF/lib/" - "spring-boot-loader": - "org/" - "snapshot-dependencies": - "application": - "BOOT-INF/classes/" - "BOOT-INF/classpath.idx" - "BOOT-INF/layers.idx" - "META-INF/"

Di luar kotak, Spring Boot menyediakan empat lapisan:

  • pergantungan : kebergantungan khas dari pihak ketiga
  • snapshot-dependencies : kebergantungan snapshot dari pihak ke-3
  • sumber : sumber statik
  • aplikasi : kod dan sumber aplikasi

The goal is to place application code and third-party libraries into layers that reflect how often they change.

For example, application code is likely what changes most frequently, so it gets its own layer. Further, each layer can evolve on its own, and only when a layer has changed will it be rebuilt for the Docker image.

Now that we understand the new layered jar structure, let's look at how we can utilize it to make Docker images.

4.1. Creating Layered Jars

First, we have to set up our project to create a layered jar. With Maven, this means adding a new configuration to the Spring Boot plugin section of our POM:

 org.springframework.boot spring-boot-maven-plugin   true   

With this configuration, the Maven package command (along with any of its dependent commands) will generate a new layered jar using the four default layers mentioned previously.

4.2. Viewing and Extracting Layers

Next, we need to extract the layers from the jar so that the Docker image will have the proper layers.

To examine the layers of any layered jar, we can run the command:

java -Djarmode=layertools -jar demo-0.0.1.jar list

Then to extract them, we would run:

java -Djarmode=layertools -jar demo-0.0.1.jar extract

4.3. Creating the Docker Image

The easiest way to incorporate these layers into a Docker image is by using a Dockerfile:

FROM adoptopenjdk:11-jre-hotspot as builder ARG JAR_FILE=target/*.jar COPY ${JAR_FILE} application.jar RUN java -Djarmode=layertools -jar application.jar extract FROM adoptopenjdk:11-jre-hotspot COPY --from=builder dependencies/ ./ COPY --from=builder snapshot-dependencies/ ./ COPY --from=builder spring-boot-loader/ ./ COPY --from=builder application/ ./ ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]

This Dockerfile extracts the layers from our fat jar, then copies each layer into the Docker image. Each COPY directive results in a new layer in the final Docker image.

If we build this Dockerfile, we can see each layer from the layered jar get added to the Docker image as its own layer:

... Step 6/10 : COPY --from=builder dependencies/ ./ ---> 2c631b8f9993 Step 7/10 : COPY --from=builder snapshot-dependencies/ ./ ---> 26e8ceb86b7d Step 8/10 : COPY --from=builder spring-boot-loader/ ./ ---> 6dd9eaddad7f Step 9/10 : COPY --from=builder application/ ./ ---> dc80cc00a655 ...

5. Conclusion

Dalam tutorial ini, kami telah melihat pelbagai cara untuk membina gambar Docker dengan Spring Boot. Dengan menggunakan buildpacks, kita dapat memperoleh gambar Docker yang sesuai tanpa plat nama atau konfigurasi tersuai. Atau, dengan sedikit usaha lagi, kita dapat menggunakan balang berlapis untuk mendapatkan gambar Docker yang lebih disesuaikan.

Semua contoh dalam tutorial ini boleh didapati di GitHub.

Untuk maklumat lebih lanjut mengenai penggunaan Java dan Docker, lihat tutorial mengenai jib.