[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"global-header-tutorials-static":3,"article-spring-boot-multi-stage-build-with-docker":4,"initial-similar-fetch":23},[],{"alias":5,"title":6,"description":7,"content":8,"thumbnail":9,"keywords":10,"categories":18,"tags":21,"createdAt":22},"spring-boot-multi-stage-build-with-docker","Creating spring boot multi-stage build with docker","How to create a Spring Boot multi-stage build with Docker","{\"type\":\"doc\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"In this tutorial, we are going to learn how to build and run our Spring Boot application using Docker.  First, we will pre-build our application to generate the fat jar file, and Docker will later utilize it for deployment. Later, we will deep dive into a multi-stage build.\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Before we move forward, you can follow some of our other tutorials.\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"link\",\"attrs\":{\"href\":\"https:\u002F\u002Fcsbyte.com\u002Fblog\u002Fhow-to-install-and-setup-the-docker-on-ubuntu\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer nofollow\",\"class\":null,\"title\":null}}],\"text\":\"How to install and setup the docker on Ubuntu\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"link\",\"attrs\":{\"href\":\"https:\u002F\u002Fcsbyte.com\u002Fblog\u002Fdeploy-spring-boot-application-with-docker\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer nofollow\",\"class\":null,\"title\":null}}],\"text\":\"Deploy Spring Boot Application with Docker on Ubuntu Server\"}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":2},\"content\":[{\"type\":\"text\",\"text\":\"Adding Spring profile for Docker\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"We are deploying the application with Docker, so first, we will configure the Docker profile for different configurations.\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"link\",\"attrs\":{\"href\":\"https:\u002F\u002Fcsbyte.com\u002Fblog\u002Fconfigure-profile-in-spring-boot\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer nofollow\",\"class\":null,\"title\":null}}],\"text\":\"Configure different spring profiles in spring boot application\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Inside \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"application.yml\"},{\"type\":\"text\",\"text\":\" file\"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"java\"},\"content\":[{\"type\":\"text\",\"text\":\"server.port: 8001\\n\\nlogging:\\n  level:\\n    root: INFO\\n    com.csbyte: DEBUG\\n\\n---\\nspring.config.activate.on-profile: docker\\nserver.port: 8080\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Here, we are separating the local environment to docker environment by dashes(---). And set the profile to \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"docker\"},{\"type\":\"text\",\"text\":\". \"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"This is a simple configuration that only has a different port for the \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"docker\"},{\"type\":\"text\",\"text\":\" profile.\"}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":3},\"content\":[{\"type\":\"text\",\"text\":\"Build The Changes\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Move to the project directory and build the project\"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"bash\"},\"content\":[{\"type\":\"text\",\"text\":\".\u002Fgradlew build\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"It will create the fat jar file inside \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"build\u002Flibs\"},{\"type\":\"text\",\"text\":\" \"}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":2},\"content\":[{\"type\":\"text\",\"text\":\"Build the Docker image\"}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":3},\"content\":[{\"type\":\"text\",\"text\":\"Create Docker File\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Let's create a Dockerfile inside the root directory in your project.\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Note: the Docker file must not contain any extension.\"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"bash\"},\"content\":[{\"type\":\"text\",\"text\":\"FROM eclipse-temurin:17-jdk-alpine\\n\\nEXPOSE 8080\\n\\nADD .\u002Fbuild\u002Flibs\u002F*.jar app.jar\\n\\nENTRYPOINT [\\\"java\\\", \\\"-jar\\\", \\\"\u002Fapp.jar\\\"]\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Here, we are using JDK 17 if you want the latest version of Java used accordingly. The setup for the JDK 25 will be as follows.\"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"bash\"},\"content\":[{\"type\":\"text\",\"text\":\"FROM eclipse-temurin:25-jre-alpine\\n\\nEXPOSE 8080\\n\\nADD .\u002Fbuild\u002Flibs\u002F*.jar app.jar\\n\\nENTRYPOINT [\\\"java\\\", \\\"-jar\\\", \\\"\u002Fapp.jar\\\"]\"}]},{\"type\":\"bulletList\",\"content\":[{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"The Docker image for JDK 17 is used\"}]}]},{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Port 8080 is exposed to the other Docker container or the internet.\"}]}]},{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"The fat Jar file will be added from the directory \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"build\u002Flibs\"},{\"type\":\"text\",\"text\":\"  that we built previously.\"}]}]},{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"ENTRYPOINT\"},{\"type\":\"text\",\"text\":\"  command is used by Docker to start the container based on the Docker image i.e \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"java -jar \u002Fapp.jar\"}]}]}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Here are some disadvantages of using these methods.\"}]},{\"type\":\"bulletList\",\"content\":[{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"When the Docker container starts up, the fat JAR will take time to unpack.\"}]}]},{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Since the fat JAR is big, if we want to deploy repeated changes to the code, running the Docker deployment layer is not optimal.\"}]}]}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"This leads to the multi-stage build.\"}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":3},\"content\":[{\"type\":\"text\",\"text\":\"Multi-Stage Build\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Let's create the multi-stage build Docker file.\"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"bash\"},\"content\":[{\"type\":\"text\",\"text\":\"FROM eclipse-temurin:17-jdk-alpine AS builder\\nWORKDIR extracted\\nADD .\u002Fbuild\u002Flibs\u002F*.jar app.jar\\nRUN java -Djarmode=layertools -jar app.jar extract\\n\\nFROM eclipse-temurin:17-jdk-alpine\\nWORKDIR app\\nCOPY --from=builder extracted\u002Fdependencies\u002F .\u002F\\nCOPY --from=builder extracted\u002Fspring-boot-loader\u002F .\u002F\\nCOPY --from=builder extracted\u002Fsnapshot-dependencies\u002F .\u002F\\nCOPY --from=builder extracted\u002Fapplication\u002F .\u002F\\n\\nEXPOSE 8080\\n\\nENTRYPOINT [\\\"java\\\", \\\"org.springframework.boot.loader.launch.JarLauncher\\\"]\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"This makes it possible to extract the fat JAR content into a number of folders. \"}]},{\"type\":\"bulletList\",\"content\":[{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"FROM eclipse-temurin:17-jdk-alpine AS builder\"},{\"type\":\"text\",\"text\":\"  it will pull the JDK image from Temurin and named as \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"builder\"},{\"type\":\"text\",\"text\":\".\"}]}]},{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"We have created the working directory as \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"extracted\"},{\"type\":\"text\",\"text\":\" and added the fat JAR file to this directory.\"}]}]},{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"RUN java -Djarmode=layertools -jar app.jar extract\"},{\"type\":\"text\",\"text\":\" the build stage, run this command to perform the extraction of the fat JAR file into its working directory.\"}]}]},{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"FROM eclipse-temurin:17-jdk-alpine\"},{\"type\":\"text\",\"text\":\" it will use the same Docker image and copy the files from the builder stage folders. \"}]}]},{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"--from=builder extracted\u002Fdependencies\u002F\"},{\"type\":\"text\",\"text\":\"  third-party libraries like Hibernate, which change less frequently. So they are copied first. Docker cache this layer\"}]}]},{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"--from=builder extracted\u002Fspring-boot-loader\u002F\"},{\"type\":\"text\",\"text\":\" handling launching the application. This contains the classes that are responsible for launching the application.\"}]}]},{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"--from=builder extracted\u002Fsnapshot-dependencies\u002F\"},{\"type\":\"text\",\"text\":\"  contains snapshot dependencies, if any.\"}]}]},{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"--from=builder extracted\u002Fapplication\u002F\"},{\"type\":\"text\",\"text\":\" our Spring Boot classes like controller, services, configuration classes.  Changes in the app code will invalidate and build other heavy-lifting dependencies that are not required to build each time.\"}]}]},{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"loader.launch.JarLauncher\"},{\"type\":\"text\",\"text\":\" Instead of \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"java -jar app.jar\"},{\"type\":\"text\",\"text\":\" (which forces Java to uncompress files at startup), it directly invokes Spring Boot's JarLauncher. Resulting in faster container startup times and slightly lower memory consumption\"}]}]}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":3},\"content\":[{\"type\":\"text\",\"text\":\"Build Image\"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"bash\"},\"content\":[{\"type\":\"text\",\"text\":\"docker build -t product-service .\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Make sure to use your own app instead of \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"product-service\"},{\"type\":\"text\",\"text\":\" .\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"The output looks something like this.\"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"bash\"},\"content\":[{\"type\":\"text\",\"text\":\"[+] Building 0.6s (14\u002F14) FINISHED                                                                                                                                                                                             docker:default\\n => [internal] load build definition from Dockerfile                                                                                                                                                                                     0.0s\\n => => transferring dockerfile: 522B                                                                                                                                                                                                     0.0s\\n => [internal] load metadata for docker.io\u002Flibrary\u002Feclipse-temurin:17-jdk-alpine                                                                                                                                                         0.4s\\n => [internal] load .dockerignore                                                                                                                                                                                                        0.0s\\n => => transferring context: 2B   \"}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":3},\"content\":[{\"type\":\"text\",\"text\":\"Run the Docker image\"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"bash\"},\"content\":[{\"type\":\"text\",\"text\":\"docker run -d --name product-service -p8080:8080 -e SPRING_PROFILES_ACTIVE=docker product-service\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"This will run the application. You can test the endpoints of your application.\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"In this tutorial, we learn how to set up  the multi-stage build for a Spring Boot application. By doing so, we are able to create a high-performance, faster container startup application deployment.\"}]}]}","\u002Fuploads\u002Fthumbnails\u002F8931e2f7-a669-4fbb-855b-5ebe396f462e_multi-stage-build-docke.jpeg",[11,12,13,14,15,16,17],"programming","coding","spring-boot-4","java","spring","spring-boot","spring-framework-7",[19,20],"Spring Framework","Spring Boot",[15,16],"2026-06-20T06:34:41.356Z",[24,31,37,43,49,55,61,67,72,78,84,90],{"alias":25,"title":26,"description":27,"thumbnail":28,"createdAt":29,"tutorialAlias":30,"lessonAlias":30},"configure-profile-in-spring-boot","Configure different spring profiles in spring boot application","Managing Spring Boot profiles for different environments along with Docker","\u002Fuploads\u002Fthumbnails\u002F59a52e59-4b56-469d-8902-41af5e0f13dd_Spring-profil.jpeg","2026-06-20T04:51:27.098Z",null,{"alias":32,"title":33,"description":34,"thumbnail":35,"createdAt":36,"tutorialAlias":30,"lessonAlias":30},"global-exception-handling-in-spring-boot","Implementing Robust Global Exception Handling in Spring Boot","How to Handle Errors in Spring Boot: An Architectural Guide","https:\u002F\u002Fapi.csbyte.com\u002Fuploads\u002Feditor\u002F554489e1-d142-4ea5-a393-994a13d7b113_exception-handling.png","2026-06-12T17:15:16.253Z",{"alias":38,"title":39,"description":40,"thumbnail":41,"createdAt":42,"tutorialAlias":30,"lessonAlias":30},"spring-boot-create-libraries-gradle","Building Reusable Spring Boot Libraries with Gradle","Architectural Guide: Building Reusable Spring Boot Libraries with Gradle","https:\u002F\u002Fapi.csbyte.com\u002Fuploads\u002Feditor\u002Ff4fb088d-1018-4d2b-ae6c-cdd5d0fd60ae_spring-Initializr.png","2026-06-12T15:55:20.994Z",{"alias":44,"title":45,"description":46,"thumbnail":47,"createdAt":48,"tutorialAlias":30,"lessonAlias":30},"multi-build-project-gradle-spring-boot","Setting up a multi-project build in Gradle for Spring Boot","How to set up a multi-project build in Gradle for Spring Boot","https:\u002F\u002Fapi.csbyte.com\u002Fuploads\u002Feditor\u002Fd43933e4-a7a3-404b-a300-8f02db98f549_multi-build-project.png","2026-06-12T04:15:23.045Z",{"alias":50,"title":51,"description":52,"thumbnail":53,"createdAt":54,"tutorialAlias":30,"lessonAlias":30},"java-version-mismatch-gradle","Java Version Mismatch for Gradle Build","How to Fix Gradle Error: Dependency requires at least JVM runtime version 17. This build uses a Java 8 JVM","\u002Fuploads\u002Fthumbnails\u002Fa4c6c910-5623-4db9-93f5-a515135adb99_gradle_version_mismatc.jpeg","2026-06-09T12:15:21.729Z",{"alias":56,"title":57,"description":58,"thumbnail":59,"createdAt":60,"tutorialAlias":30,"lessonAlias":30},"constructor-confusion-in-spring","Constructor Confusion in Spring Framework","Constructor Confusion and how to handle it in Spring Framework","\u002Fuploads\u002Fthumbnails\u002Fd0f09fc0-e1f9-49d1-bf9a-7d1c41050196_di_confusio.jpeg","2026-05-21T14:13:31.437Z",{"alias":62,"title":63,"description":64,"thumbnail":65,"createdAt":66,"tutorialAlias":30,"lessonAlias":30},"dependency-pull-lookup-spring","Dependency Pull and Contextualized Dependency Lookup in Spring Framework","Dependency Pull and Contextualized Dependency Lookup IoC Types in Spring Framework","\u002Fuploads\u002Fthumbnails\u002Fd1132443-313b-4dce-b713-55f356ef6051_depndency_pull.png","2026-05-20T15:26:06.494Z",{"alias":68,"title":69,"description":69,"thumbnail":70,"createdAt":71,"tutorialAlias":30,"lessonAlias":30},"types-of-dependency-injection-spring","Types of Dependency Injection in Spring Framework","\u002Fuploads\u002Fthumbnails\u002Fafb32399-6dda-41c4-b07c-7decb8257bbb_di_constructor_sette.jpeg","2026-05-19T17:01:51.972Z",{"alias":73,"title":74,"description":75,"thumbnail":76,"createdAt":77,"tutorialAlias":30,"lessonAlias":30},"spring-framework-project-for-gradle-with-intellij-idea","How to create a clean Spring Framework project for Gradle with IntelliJ IDEA","Create a clean Spring Framework project for Gradle with IntelliJ IDEA","https:\u002F\u002Fapi.csbyte.com\u002Fuploads\u002Feditor\u002F0e4abad5-17e2-4311-8cf0-7d8f67af975a_spring-framework.png","2026-05-19T10:28:20.866Z",{"alias":79,"title":80,"description":81,"thumbnail":82,"createdAt":83,"tutorialAlias":30,"lessonAlias":30},"spring-dependency-injection-and-inversion-control","Dependency Injection (DI) and Inversion of Control (IoC) in Spring","Mastering Dependency Injection (DI) and Inversion of Control (IoC) in Spring: A Practical Guide for Building a Notification System","\u002Fuploads\u002Fthumbnails\u002F53c64b94-f188-40b4-9ae9-ad97612d688b_spring_d.jpeg","2026-05-19T05:31:45.138Z",{"alias":85,"title":86,"description":87,"thumbnail":88,"createdAt":89,"tutorialAlias":30,"lessonAlias":30},"setting-nginx-ssl-for-spring-boot-application","Setup Nginx and SSL for Spring Boot Application","Setting Nginx as a reverse proxy in our Spring Boot application","\u002Fuploads\u002Fthumbnails\u002F5433c987-9e86-4d90-9cce-a831d1598ba4_spring-boot-nginx.png","2026-05-04T05:36:23.075Z",{"alias":91,"title":92,"description":93,"thumbnail":94,"createdAt":95,"tutorialAlias":30,"lessonAlias":30},"deploy-spring-boot-application-with-docker","Deploy Spring Boot Application with Docker on Ubuntu Server","The ultimate guide to deploying our Spring Boot application with Docker on an Ubuntu server","https:\u002F\u002Fapi.csbyte.com\u002Fuploads\u002Feditor\u002F55a11844-d1e9-4e83-80e5-c6bb6df7d58b_intellij-idea-build.png","2026-05-03T05:58:55.642Z"]