{"id":90296,"date":"2019-04-01T19:44:31","date_gmt":"2019-04-01T16:44:31","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=90296"},"modified":"2019-04-08T09:11:11","modified_gmt":"2019-04-08T06:11:11","slug":"build-spring-microservices-dockerize-production","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2019\/04\/build-spring-microservices-dockerize-production.html","title":{"rendered":"Build Spring Microservices and Dockerize Them for Production"},"content":{"rendered":"<p><span style=\"font-size: 20px;\"><b>\u201cI love writing authentication and authorization code.\u201d ~ No Java Developer Ever.<\/b> Tired of building the same login screens over and over? <a href=\"https:\/\/developer.okta.com\/signup\/?utm_campaign=text_website_all_multiple_dev_ciam_spring-microservices-dockerize_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Try the Okta API for hosted authentication, authorization, and multi-factor auth.<\/a><\/span><\/p>\n<p>In this post, you\u2019ll learn about microservices architecture and how to implement it using Spring Boot. After creating some projects with the technique, you will deploy the artifacts as Docker containers and will simulate a&nbsp;<em>container orchestrator<\/em>&nbsp;(such as Kubernetes) using&nbsp;<em>Docker Compose<\/em>&nbsp;for simplification. The icing on the cake will be authentication integration using Spring Profiles; you will see how to enable it with a production profile.<\/p>\n<p>But first, let\u2019s talk about microservices.<\/p>\n<h2 class=\"wp-block-heading\" id=\"understand-a-modern-microservice-architecture\">Understand a Modern Microservice Architecture<\/h2>\n<p>Microservices, as opposed to a monolith architecture, dictates you have to divide your application into small, logically related, pieces. These pieces are independent software that communicates with other pieces using HTTP or messages, for example.<\/p>\n<p>There is some discussion of what size&nbsp;<em>micro<\/em>&nbsp;is. Some say a microservice is software that can be created in a single sprint; others say microservices can have bigger size if it is logically related (you can\u2019t mix apples and oranges, for example). I agree with&nbsp;<a href=\"https:\/\/martinfowler.com\/articles\/microservices.html\">Martin Fowler<\/a>&nbsp;and think size doesn\u2019t matter that much, and it\u2019s more related to the style.<\/p>\n<p>There are many advantages to microservices:<\/p>\n<ul class=\"wp-block-list\">\n<li><strong>No high coupling risk<\/strong>&nbsp;&#8211; Since each app lives in a different process, it is impossible to create classes that talk to each other.<\/li>\n<li><strong>Easy scaling<\/strong>&nbsp;&#8211; As you already know, every service is an independent piece of software. As such, it can be scaled up or down on demand. Moreover, since the code is&nbsp;<em>smaller<\/em>&nbsp;than a monolith, it probably will start up faster.<\/li>\n<li><strong>Multiple stacks<\/strong>&nbsp;&#8211; You can use the best software stack for every service. No more need to use Java when, say, Python is better for what you\u2019re building.<\/li>\n<li><strong>Fewer merges and code conflicts<\/strong>&nbsp;&#8211; As every service is a different repository, it is easier to handle and review commits.<\/li>\n<\/ul>\n<p>However, there are some drawbacks:<\/p>\n<ul class=\"wp-block-list\">\n<li>You have a new enemy &#8211;&nbsp;<strong>network issues<\/strong>. Is the service up? What can you do if the service is down?<\/li>\n<li><strong>Complex deployment process<\/strong>&nbsp;&#8211; OK CI\/CD is here, but you now have one workflow for each service. If they use different stacks, it\u2019s possible you can\u2019t even replicate a workflow for each.<\/li>\n<li><strong>More complex and hard-to-understand architecture<\/strong>&nbsp;&#8211; it depends on how you design it, but consider this: if you don\u2019t know what a method is doing, you can read its code. In a microservice architecture, this method may be in another project, and you may not even have the code.<\/li>\n<\/ul>\n<p>Nowadays, it\u2019s commonly accepted that you should&nbsp;<a href=\"https:\/\/martinfowler.com\/bliki\/MonolithFirst.html\">avoid a microservice architecture at first<\/a>. After some iterations, the code division will become clearer as will the demands of your project. It is often too expensive to handle microservices until your development team starts into small projects.<\/p>\n<h2 class=\"wp-block-heading\" id=\"build-microservices-in-spring-with-docker\">Build Microservices in Spring with Docker<\/h2>\n<p>You\u2019ll build two projects in this tutorial: a service (school-service) and a UI (school_ui). The service provides the persistent layer and business logic, and the UI provides the graphical user interface. Connecting them is possible with minimal configuration.<\/p>\n<p>After the initial setup, I\u2019ll talk about discovery and configuration services. Both services are an essential part of any massively distributed architecture. To prove this point, you will integrate it with OAuth 2.0 and use the configuration project to set the OAuth 2.0 keys.<\/p>\n<p>Finally, each project will be transformed into a Docker image. Docker Compose will be used to simulate a&nbsp;<em>container orchestrator<\/em>as Compose will manage every container with an internal network between the services.<\/p>\n<p>Lastly, Spring profiles will be introduced to change configuration based on the environment currently appropriately assigned. That way, you will have two OAuth 2.0 environments: one for development, and other for production.<\/p>\n<p>Fewer words, more code! Clone this tutorial\u2019s repository and check out the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">start<\/code>&nbsp;branch.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">git clone -b start https:\/\/github.com\/oktadeveloper\/okta-spring-microservices-docker-example.git <\/pre>\n<p>The root&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">pom.xml<\/code>&nbsp;file is not a requirement. However, it can be helpful to manage multiple projects at once. Let\u2019s look inside:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;project xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\" xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n    xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\"&gt;\n    &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\n    &lt;groupId&gt;com.okta.developer.docker_microservices&lt;\/groupId&gt;\n    &lt;artifactId&gt;parent-pom&lt;\/artifactId&gt;\n    &lt;version&gt;0.0.1-SNAPSHOT&lt;\/version&gt;\n    &lt;packaging&gt;pom&lt;\/packaging&gt;\n    &lt;name&gt;parent-project&lt;\/name&gt;\n    &lt;modules&gt;\n        &lt;module&gt;school-service&lt;\/module&gt;\n        &lt;module&gt;school-ui&lt;\/module&gt;    \n    &lt;\/modules&gt;\n&lt;\/project&gt;\n<\/pre>\n<p>This is called an&nbsp;<em>aggregate project<\/em>&nbsp;because it aggregates child projects. It is useful for running the same Maven task on all declared modules. The modules do not need to use the root module as a parent.<\/p>\n<p>There are two modules available: a school service, and a school UI.<\/p>\n<h2 class=\"wp-block-heading\" id=\"the-school-service-microservice\">The School Service Microservice<\/h2>\n<p>The&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-service<\/code>&nbsp;directory contains a Spring Boot project that acts as the project\u2019s persistence layer and business rules. In a more complex scenario, you would have more services like this. The project was created using the always excellent&nbsp;<a href=\"https:\/\/start.spring.io\/\">Spring Initializr<\/a>&nbsp;with the following configuration:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/initializr-service-1024x447.png\" alt=\"Spring Microservices\" class=\"wp-image-90302\" width=\"768\" height=\"335\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/initializr-service-1024x447.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/initializr-service-300x131.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/initializr-service-768x335.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/initializr-service.png 1203w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/><\/figure>\n<\/div>\n<ul class=\"wp-block-list\">\n<li>Group &#8211;&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">com.okta.developer.docker_microservices<\/code><\/li>\n<li>Artifact &#8211;&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-service<\/code><\/li>\n<li>Dependencies &#8211; JPA, Web, Lombok, H2<\/li>\n<\/ul>\n<p>You can get more details about this project by reading&nbsp;<a href=\"https:\/\/developer.okta.com\/blog\/2019\/02\/20\/spring-boot-with-postgresql-flyway-jsonb?utm_campaign=text_website_all_multiple_dev_ciam_spring-microservices-dockerize_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Spring Boot with PostgreSQL, Flyway, and JSONB<\/a>. To summarize, it has the entities&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">TeachingClass<\/code>,&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Course,<\/code>&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Student<\/code>&nbsp;and uses&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">TeachingClassServiceDB<\/code>&nbsp;and&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">TeachingClassController<\/code>to expose some data through a REST API. To test it, open a terminal, navigate to the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-service<\/code>&nbsp;directory, and run the command below:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">.\/mvnw spring-boot:run<\/pre>\n<p>The application will start on port&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">8081<\/code>&nbsp;(as defined in file&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-service\/src\/main\/resources\/application.properties<\/code>), so you should be able to navigate to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:8081<\/code>&nbsp;and see the returned data.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:js\">&gt; curl http:\/\/localhost:8081\n[\n   {\n      \"classId\":13,\n      \"teacherName\":\"Profesor Jirafales\",\n      \"teacherId\":1,\n      \"courseName\":\"Mathematics\",\n      \"courseId\":3,\n      \"numberOfStudents\":2,\n      \"year\":1988\n   },\n   {\n      \"classId\":14,\n      \"teacherName\":\"Profesor Jirafales\",\n      \"teacherId\":1,\n      \"courseName\":\"Spanish\",\n      \"courseId\":4,\n      \"numberOfStudents\":2,\n      \"year\":1988\n   },\n   {\n      \"classId\":15,\n      \"teacherName\":\"Professor X\",\n      \"teacherId\":2,\n      \"courseName\":\"Dealing with unknown\",\n      \"courseId\":5,\n      \"numberOfStudents\":2,\n      \"year\":1995\n   },\n   {\n      \"classId\":16,\n      \"teacherName\":\"Professor X\",\n      \"teacherId\":2,\n      \"courseName\":\"Dealing with unknown\",\n      \"courseId\":5,\n      \"numberOfStudents\":1,\n      \"year\":1996\n   }\n]\n<\/pre>\n<h2 class=\"wp-block-heading\" id=\"the-spring-based-school-ui-microservice\">The Spring-Based School UI Microservice<\/h2>\n<p>The school UI is, as the name says, the user interface that utilizes School Service. It was created using Spring Initializr with the following options:<\/p>\n<ul class=\"wp-block-list\">\n<li>Group &#8211;&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">com.okta.developer.docker_microservices<\/code><\/li>\n<li>Artifact &#8211;&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui<\/code><\/li>\n<li>Dependencies &#8211; Web, Hateoas, Thymeleaf, Lombok<\/li>\n<\/ul>\n<p>The UI is a single web page that lists the classes available on the database. To get the information, it connects with the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-service<\/code>&nbsp;through a configuration in file&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui\/src\/main\/resources\/application.properties<\/code>.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">service.host=localhost:8081<\/pre>\n<p>The class&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">SchoolController<\/code>&nbsp;class has all the logic to query the service:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.developer.docker_microservices.ui.controller;\n\nimport com.okta.developer.docker_microservices.ui.dto.TeachingClassDto;\nimport org.springframework.beans.factory.annotation.*;\nimport org.springframework.core.ParameterizedTypeReference;\nimport org.springframework.http.*;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.*;\nimport org.springframework.web.client.RestTemplate;\nimport org.springframework.web.servlet.ModelAndView;\nimport java.util.List;\n\n@Controller\n@RequestMapping(\"\/\")\npublic class SchoolController {\n    private final RestTemplate restTemplate;\n    private final String serviceHost;\n\n    public SchoolController(RestTemplate restTemplate, @Value(\"${service.host}\") String serviceHost) {\n        this.restTemplate = restTemplate;\n        this.serviceHost = serviceHost;\n    }\n\n    @RequestMapping(\"\")\n    public ModelAndView index() {\n        return new ModelAndView(\"index\");\n    }\n\n    @GetMapping(\"\/classes\")\n    public ResponseEntity&lt;List&lt;TeachingClassDto&gt;&gt; listClasses(){\n        return restTemplate\n                .exchange(\"http:\/\/\"+ serviceHost +\"\/class\", HttpMethod.GET, null,\n                        new ParameterizedTypeReference&lt;List&lt;TeachingClassDto&gt;&gt;() {});\n    }\n}\n<\/pre>\n<p>As you can see, there is a hard-coded location for the service. You can change the property setting with an environment variable like this&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">-Dservice.host=localhost:9090<\/code>. Still, it has to be manually defined. How about having many instances of&nbsp;<em>school-service<\/em>&nbsp;application? Impossible at the current stage.<\/p>\n<p>With&nbsp;<em>school-service<\/em>&nbsp;turned on, start&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui<\/code>, and navigate to it in a browser at&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:8080<\/code>:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">.\/mvnw spring-boot:run<\/pre>\n<p>You should see a page like the following:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"479\" height=\"184\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/school-ui.png\" alt=\"Spring Microservices\" class=\"wp-image-90303\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/school-ui.png 479w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/school-ui-300x115.png 300w\" sizes=\"(max-width: 479px) 100vw, 479px\" \/><\/figure>\n<\/div>\n<h2 class=\"wp-block-heading\" id=\"build-a-discovery-server-with-spring-cloud-and-eureka\">Build a Discovery Server with Spring Cloud and Eureka<\/h2>\n<p>Now you have a working application that uses two services to provide the information to end-user. What is wrong with it? In modern applications, developers (or operations) usually don\u2019t know where or what port an application might be deployed on. The deployment should be automated so that no one&nbsp;<em>cares<\/em>&nbsp;about server names and physical location. (Unless you work inside a data center. If you do, I hope you care!)<\/p>\n<p>Nonetheless, it is essential to have a tool that helps the services to discover their counterparts. There are many solutions available, and for this tutorial, we are going to use&nbsp;<em>Eureka<\/em>&nbsp;from Netflix as it has outstanding Spring support.<\/p>\n<p>Go back to&nbsp;<a href=\"http:\/\/start.spring.io\/\">start.spring.io<\/a>&nbsp;and create a new project as follows:<\/p>\n<ul class=\"wp-block-list\">\n<li>Group:&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">com.okta.developer.docker_microservices<\/code><\/li>\n<li>Artifact:&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">discovery<\/code><\/li>\n<li>Dependencies: Eureka Server<\/li>\n<\/ul>\n<p>Edit the main&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">DiscoveryApplication.java<\/code>&nbsp;class to add an&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@EnableEurekaServer<\/code>&nbsp;annotation:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.developer.docker_microservices.discovery;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;\n\n@SpringBootApplication\n@EnableEurekaServer\npublic class DiscoveryApplication {\n    public static void main(String[] args) {\n        SpringApplication.run(DiscoveryApplication.class, args);\n    }\n}\n<\/pre>\n<p>And, you\u2019ll need to update its&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">application.properties<\/code>&nbsp;file so it runs on port 8761 and doesn\u2019t try to register with itself.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">spring.application.name=discovery-server\nserver.port=8761\neureka.client.register-with-eureka=false\neureka.client.fetch-registry=false<\/pre>\n<p>Let\u2019s define each property:<\/p>\n<ul class=\"wp-block-list\">\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">spring.application.name<\/code>&nbsp;&#8211; The name of the application, also used by the discovery service to&nbsp;<em>discover<\/em>&nbsp;a service. You\u2019ll see that every other application has an application name too.<\/li>\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">server.port<\/code>&nbsp;&#8211; The port the server is running.&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">8761<\/code>&nbsp;is the default port for Eureka server.<\/li>\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">eureka.client.register-with-eureka<\/code>&nbsp;&#8211; Tells Spring not to register itself into the discovery service.<\/li>\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">eureka.client .fetch-registry<\/code>&nbsp;&#8211; Indicates this instance should not fetch discovery information from the server.<\/li>\n<\/ul>\n<p>Now, run and access&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:8761<\/code>.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">.\/mvnw spring-boot:run<\/pre>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/eureka-empty-1024x310.png\" alt=\"Spring Microservices\" class=\"wp-image-90304\" width=\"768\" height=\"233\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/eureka-empty-1024x310.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/eureka-empty-300x91.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/eureka-empty-768x232.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/eureka-empty.png 1898w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/><\/figure>\n<\/div>\n<p>The screen above shows the Eureka server ready to register new services. Now, it is time to change&nbsp;<em>school-service<\/em>&nbsp;and&nbsp;<em>school-ui<\/em>to use it.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p><strong>NOTE:<\/strong>&nbsp;If you receive a&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">ClassNotFoundException: javax.xml.bind.JAXBContext<\/code>&nbsp;error on startup, it\u2019s because you\u2019re running on Java 11. You can add JAXB dependencies to your&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">pom.xml<\/code>&nbsp;to fix this.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:xml\">&lt;dependency&gt;\n  &lt;groupId&gt;javax.xml.bind&lt;\/groupId&gt;\n  &lt;artifactId&gt;jaxb-api&lt;\/artifactId&gt;\n  &lt;version&gt;2.3.1&lt;\/version&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n  &lt;groupId&gt;org.glassfish.jaxb&lt;\/groupId&gt;\n  &lt;artifactId&gt;jaxb-runtime&lt;\/artifactId&gt;\n  &lt;version&gt;2.3.2&lt;\/version&gt;\n&lt;\/dependency&gt;\n<\/pre>\n<h3 class=\"wp-block-heading\" id=\"use-service-discovery-to-communicate-between-microservices\">Use Service Discovery to Communicate Between Microservices<\/h3>\n<p>First, it is important to add the required dependencies. Add the following to both&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">pom.xml<\/code>&nbsp;file (in the&nbsp;<em>school-service<\/em>&nbsp;and&nbsp;<em>school-ui<\/em>&nbsp;projects):<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:xml\">&lt;dependency&gt;\n    &lt;groupId&gt;org.springframework.cloud&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-cloud-starter-netflix-eureka-client&lt;\/artifactId&gt;\n&lt;\/dependency&gt;\n<\/pre>\n<p>This module is part of the Spring Cloud initiative and, as such, needs a new dependency management node as follows (don\u2019t forget to add to both projects):<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:xml\">&lt;dependencyManagement&gt;\n    &lt;dependencies&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.springframework.cloud&lt;\/groupId&gt;\n            &lt;artifactId&gt;spring-cloud-dependencies&lt;\/artifactId&gt;\n            &lt;version&gt;${spring-cloud.version}&lt;\/version&gt;\n            &lt;type&gt;pom&lt;\/type&gt;\n            &lt;scope&gt;import&lt;\/scope&gt;\n        &lt;\/dependency&gt;\n    &lt;\/dependencies&gt;\n&lt;\/dependencyManagement&gt;\n<\/pre>\n<p>Now you need to configure both applications to register with Eureka.<\/p>\n<p>In the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">application.properties<\/code>&nbsp;file of both projects, add the following lines:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">eureka.client.serviceUrl.defaultZone=${EUREKA_SERVER:http:\/\/localhost:8761\/eureka}\nspring.application.name=school-service<\/pre>\n<p>Don\u2019t forget to change the application name from&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-service<\/code>&nbsp;to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui<\/code>&nbsp;in the&nbsp;<em>school-ui<\/em>&nbsp;project. Notice there is a new kind of parameter in the first line:&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">{EUREKA_SERVER:http:\/\/localhost:8761\/eureka}<\/code>. It means \u201cif environment variable EUREKA_SERVER exists, use its value, if not, here\u2019s a default value.\u201d This will be useful in future steps. ;)<\/p>\n<p>You know what? Both applications are ready to register themselves into the discovery service. You don\u2019t need to do anything more. Our primary objective is that&nbsp;<em>school-ui<\/em>&nbsp;project does not need to know&nbsp;<em>where<\/em>&nbsp;school-service is. As such, you need to change&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">SchoolController<\/code>&nbsp;(in the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui<\/code>&nbsp;project) to use&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-service<\/code>&nbsp;in its REST endpoint. You can also remove the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">serviceHost<\/code>&nbsp;variable in this class.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.developer.docker_microservices.ui.controller;\n\nimport com.okta.developer.docker_microservices.ui.dto.TeachingClassDto;\nimport org.springframework.core.ParameterizedTypeReference;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.client.RestTemplate;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport java.util.List;\n\n@Controller\n@RequestMapping(\"\/\")\npublic class SchoolController {\n    private final RestTemplate restTemplate;\n\n    public SchoolController(RestTemplate restTemplate) {\n        this.restTemplate = restTemplate;\n    }\n\n    @RequestMapping(\"\")\n    public ModelAndView index() {\n        return new ModelAndView(\"index\");\n    }\n\n    @GetMapping(\"\/classes\")\n    public ResponseEntity&lt;List&lt;TeachingClassDto&gt;&gt; listClasses() {\n        return restTemplate\n                .exchange(\"http:\/\/school-service\/classes\", HttpMethod.GET, null,\n                        new ParameterizedTypeReference&lt;List&lt;TeachingClassDto&gt;&gt;() {});\n    }\n}\n<\/pre>\n<p>Before integrating Eureka, you had a configuration pointing out where&nbsp;<em>school-service<\/em>&nbsp;was. Now, you\u2019ve changed the service calls to use the name used by the other service: no ports, no hostname. The service you need is somewhere, and you don\u2019t need to know where.<\/p>\n<p>The&nbsp;<em>school-service<\/em>&nbsp;may have multiple instances of and it would be a good idea to load balance the calls between the instances. Thankfully, Spring has a simple solution: on the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">RestTemplate<\/code>&nbsp;bean creation, add&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@LoadBalanced<\/code>&nbsp;annotation as follows. Spring will manage multiple instance calls each time you ask something to the server.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.developer.docker_microservices.ui;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.loadbalancer.LoadBalanced;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.web.client.RestTemplate;\nimport org.springframework.web.servlet.config.annotation.*;\n\n@SpringBootApplication\npublic class UIWebApplication implements WebMvcConfigurer {\n\n    public static void main(String[] args) {\n        SpringApplication.run(UIWebApplication.class, args);\n    }\n\n    @Bean\n    @LoadBalanced\n    public RestTemplate restTemplate() {\n        return new RestTemplate();\n    }\n\n    @Override\n    public void addResourceHandlers(ResourceHandlerRegistry registry) {\n        if(!registry.hasMappingForPattern(\"\/static\/**\")) {\n            registry.addResourceHandler(\"\/static\/**\")\n                    .addResourceLocations(\"classpath:\/static\/\", \"classpath:\/static\/js\/\");\n        }\n    }\n}\n<\/pre>\n<p>Now, start restart&nbsp;<em>school-service<\/em>&nbsp;and&nbsp;<em>school-ui<\/em>&nbsp;(and keep the Discovery service up). Have a quick look at&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:8761<\/code>&nbsp;again:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/eureka-filled-1024x133.png\" alt=\"Spring Microservices\" class=\"wp-image-90305\" width=\"768\" height=\"100\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/eureka-filled-1024x133.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/eureka-filled-300x39.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/eureka-filled-768x100.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/eureka-filled.png 1337w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/><\/figure>\n<\/div>\n<p>Now your services are sharing info with the Discovery server. You can test the application again and see that it work as always. Just go to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:8080<\/code>&nbsp;in your favorite browser.<\/p>\n<h2 class=\"wp-block-heading\" id=\"add-a-configuration-server-to-your-microservices-architecture\">Add a Configuration Server to Your Microservices Architecture<\/h2>\n<p>While this configuration works, it\u2019s even better to remove any trace of configuration values in the project\u2019s source code. First, the configuration URL was removed from the project and became managed by a service. Now, you can do a similar thing for every configuration on the project using&nbsp;<a href=\"https:\/\/spring.io\/projects\/spring-cloud-config\">Spring Cloud Config<\/a>.<\/p>\n<p>First, create the configuration project using&nbsp;<a href=\"http:\/\/start.spring.io\/\">Spring Initializr<\/a>&nbsp;and the following parameters:<\/p>\n<ul class=\"wp-block-list\">\n<li>Group:&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">com.okta.developer.docker_microservices<\/code><\/li>\n<li>Artifact:&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">config<\/code><\/li>\n<li>Dependencies: Config Server, Eureka Discovery<\/li>\n<\/ul>\n<p>In the main class, add&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@EnableConfigServer<\/code>:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.developer.docker_microservices.config;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.config.server.EnableConfigServer;\n\n@SpringBootApplication\n@EnableConfigServer\npublic class ConfigApplication {\n    ...\n}<\/pre>\n<p>Add the following properties and values in the project\u2019s&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">application.properties<\/code>:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">spring.application.name=CONFIGSERVER\nserver.port=8888\nspring.profiles.active=native\nspring.cloud.config.server.native.searchLocations=.\neureka.client.serviceUrl.defaultZone=${EUREKA_SERVER:http:\/\/localhost:8761\/eureka}<\/pre>\n<p>Some explanation about the properties:<\/p>\n<ul class=\"wp-block-list\">\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">spring.profiles.active=native<\/code>&nbsp;&#8211; Indicates Spring Cloud Config must use the native file system to obtain the configuration. Normally Git repositories are used, but we are going to stick with native filesystem for simplicity sake.<\/li>\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">spring.cloud.config.server.native.searchLocations<\/code>&nbsp;&#8211; The path containing the configuration files. If you change this to a specific folder on your hard drive, make sure and create the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui.properties<\/code>&nbsp;file in it.<\/li>\n<\/ul>\n<p>Now, you need something to configure and apply to this example. How about Okta\u2019s configuration? Let\u2019s put our&nbsp;<em>school-ui<\/em>behind an authorization layer and use the property values provided by the configuration project.<\/p>\n<p>You can register for a&nbsp;<a href=\"https:\/\/developer.okta.com\/signup\/?utm_campaign=text_website_all_multiple_dev_ciam_spring-microservices-dockerize_null&amp;utm_source=jcg&amp;utm_medium=cpc\">free-forever developer account<\/a>&nbsp;that will enable you to create as many user and applications you need to use! After creating your account, create a new Web Application in Okta\u2019s dashboard (<strong>Applications<\/strong>&nbsp;&gt;&nbsp;<strong>Add Application<\/strong>):<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/okta-new-web-application.png\" alt=\"Spring Microservices\" class=\"wp-image-90306\" width=\"741\" height=\"356\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/okta-new-web-application.png 988w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/okta-new-web-application-300x144.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/okta-new-web-application-768x368.png 768w\" sizes=\"(max-width: 741px) 100vw, 741px\" \/><\/figure>\n<\/div>\n<p>And fill the next form with the following values:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/okta-new-web-application-step2.png\" alt=\"Spring Microservices\" class=\"wp-image-90307\" width=\"631\" height=\"693\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/okta-new-web-application-step2.png 841w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/okta-new-web-application-step2-273x300.png 273w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/okta-new-web-application-step2-768x844.png 768w\" sizes=\"(max-width: 631px) 100vw, 631px\" \/><\/figure>\n<\/div>\n<p>The page will return you an application ID and an secret key. Keep then safe and create a file called&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui.properties<\/code>in the root folder of the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">config<\/code>&nbsp;project with the following contents. Do not forget to populate the variable values:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">okta.oauth2.issuer=https:\/\/{yourOktaDomain}\/oauth2\/default\nokta.oauth2.clientId={yourClientId}\nokta.oauth2.clientSecret={yourClientSecret}<\/pre>\n<p>Now, run the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">config<\/code>&nbsp;project and check if its getting the configuration data properly:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">.\/mvnw spring-boot:run\n&gt; curl http:\/\/localhost:8888\/school-ui.properties\nokta.oauth2.clientId: YOUR_CLIENT_ID\nokta.oauth2.clientSecret: YOUR_CLIENT_SECRET\nokta.oauth2.issuer: https:\/\/YOUR_DOMAIN\/oauth2\/default<\/pre>\n<h3 class=\"wp-block-heading\" id=\"change-school-ui-to-use-spring-cloud-config-and-oauth-20\">Change School UI to Use Spring Cloud Config and OAuth 2.0<\/h3>\n<p>Now you need to change the Spring UI project a little bit.<\/p>\n<p>First, you need to change&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui\/pom.xml<\/code>&nbsp;and add some new dependencies:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:xml\">&lt;dependency&gt;\n    &lt;groupId&gt;org.springframework.cloud&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-cloud-starter-config&lt;\/artifactId&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;com.okta.spring&lt;\/groupId&gt;\n    &lt;artifactId&gt;okta-spring-boot-starter&lt;\/artifactId&gt;\n    &lt;version&gt;1.1.0&lt;\/version&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;org.thymeleaf.extras&lt;\/groupId&gt;\n    &lt;artifactId&gt;thymeleaf-extras-springsecurity5&lt;\/artifactId&gt;\n&lt;\/dependency&gt;\n<\/pre>\n<p>Create a new&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">SecurityConfiguration<\/code>&nbsp;class in the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">com.okta...ui.config<\/code>&nbsp;package:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.developer.docker_microservices.ui;\n\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\n\n@Configuration\n@EnableGlobalMethodSecurity(prePostEnabled = true)\npublic class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {\n\n   @Override\n    protected void configure(HttpSecurity http) throws Exception {\n        http\n            .authorizeRequests()\n                .antMatchers(\"\/\").permitAll()\n                .anyRequest().authenticated()\n            .and()\n                .logout().logoutSuccessUrl(\"\/\")\n            .and()\n                .oauth2Login();\n    }\n}\n<\/pre>\n<p>Change your&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">SchoolController<\/code>&nbsp;so only users with scope&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">profile<\/code>&nbsp;will be allowed (every authenticated user will have it).<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">import org.springframework.security.access.prepost.PreAuthorize;\n\n....\n\n@GetMapping(\"\/classes\")\n@PreAuthorize(\"hasAuthority('SCOPE_profile')\")\npublic ResponseEntity&lt;List&lt;TeachingClassDto&gt;&gt; listClasses(){\n    return restTemplate\n        .exchange(\"http:\/\/school-service\/class\", HttpMethod.GET, null,\n                new ParameterizedTypeReference&lt;List&lt;TeachingClassDto&gt;&gt;() {});\n}<\/pre>\n<p>Some configurations need to be defined at project boot time. Spring had a clever solution to locate properly and extract configuration data&nbsp;<em>before<\/em>&nbsp;context startup. You need to create a file&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">src\/main\/resources\/bootstrap.yml<\/code>&nbsp;like this:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">eureka:\n  client:\n    serviceUrl:\n      defaultZone: ${EUREKA_SERVER:http:\/\/localhost:8761\/eureka}\nspring:\n  application:\n    name: school-ui\n  cloud:\n    config:\n      discovery:\n        enabled: true\n        service-id: CONFIGSERVER\n<\/pre>\n<p>The bootstrap file creates a pre-boot Spring Application Context responsible for extracting configuration before the real application starts. You need to move all properties from&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">application.properties<\/code>&nbsp;to this file as Spring needs to know where your Eureka Server is located and how it should search for configuration. In the example above, you enabled configuration over discovery service (<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">spring.cloud.config.discovery.enabled<\/code>) and specified the Configuration&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">service-id<\/code>.<\/p>\n<p>Change your&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">application.properties<\/code>&nbsp;file so it only has one OAuth 2.0 property:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">okta.oauth2.redirect-uri=\/authorization-code\/callback<\/pre>\n<p>The last file to modify is&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">src\/main\/resources\/templates\/index.hml<\/code>. Adjust it to show a login button if the user is not authenticated, and a logout button if the user is logged in.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:xml\">&lt;!doctype html&gt;\n&lt;html lang=\"en\" xmlns:th=\"http:\/\/www.thymeleaf.org\"&gt;\n&lt;head&gt;\n    &lt;!-- Required meta tags --&gt;\n    &lt;meta charset=\"utf-8\"&gt;\n    &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\"&gt;\n\n    &lt;!-- Bootstrap CSS --&gt;\n    &lt;link rel=\"stylesheet\" href=\"https:\/\/stackpath.bootstrapcdn.com\/bootstrap\/4.1.3\/css\/bootstrap.min.css\" integrity=\"sha384-MCw98\/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO\" crossorigin=\"anonymous\"&gt;\n\n    &lt;title&gt;Hello, world!&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n&lt;nav class=\"navbar navbar-default\"&gt;\n    &lt;form method=\"post\" th:action=\"@{\/logout}\" th:if=\"${#authorization.expression('isAuthenticated()')}\" class=\"navbar-form navbar-right\"&gt;\n        &lt;input type=\"hidden\" th:name=\"${_csrf.parameterName}\" th:value=\"${_csrf.token}\" \/&gt;\n        &lt;button id=\"logout-button\" type=\"submit\" class=\"btn btn-danger\"&gt;Logout&lt;\/button&gt;\n    &lt;\/form&gt;\n    &lt;form method=\"get\" th:action=\"@{\/oauth2\/authorization\/okta}\" th:unless=\"${#authorization.expression('isAuthenticated()')}\"&gt;\n        &lt;button id=\"login-button\" class=\"btn btn-primary\" type=\"submit\"&gt;Login&lt;\/button&gt;\n    &lt;\/form&gt;\n&lt;\/nav&gt;\n\n&lt;div id=\"content\" th:if=\"${#authorization.expression('isAuthenticated()')}\"&gt;\n    &lt;h1&gt;School classes&lt;\/h1&gt;\n\n    &lt;table id=\"classes\"&gt;\n        &lt;thead&gt;\n        &lt;tr&gt;\n            &lt;th&gt;Course&lt;\/th&gt;\n            &lt;th&gt;Teacher&lt;\/th&gt;\n            &lt;th&gt;Year&lt;\/th&gt;\n            &lt;th&gt;Number of students&lt;\/th&gt;\n        &lt;\/tr&gt;\n        &lt;\/thead&gt;\n        &lt;tbody&gt;\n\n        &lt;\/tbody&gt;\n    &lt;\/table&gt;\n\n    &lt;!-- Optional JavaScript --&gt;\n    &lt;!-- jQuery first, then Popper.js, then Bootstrap JS --&gt;\n\n    &lt;script src=\"https:\/\/code.jquery.com\/jquery-3.3.1.min.js\" crossorigin=\"anonymous\"&gt;&lt;\/script&gt;\n    &lt;script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/popper.js\/1.14.3\/umd\/popper.min.js\" integrity=\"sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK\/l8WvCWPIPm49\" crossorigin=\"anonymous\"&gt;&lt;\/script&gt;\n    &lt;script src=\"https:\/\/stackpath.bootstrapcdn.com\/bootstrap\/4.1.3\/js\/bootstrap.min.js\" integrity=\"sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW\/JmZQ5stwEULTy\" crossorigin=\"anonymous\"&gt;&lt;\/script&gt;\n    &lt;script src=\"static\/js\/school_classes.js\"&gt;&lt;\/script&gt;\n&lt;\/div&gt;\n\n&lt;\/body&gt;\n&lt;\/html&gt;\n<\/pre>\n<p>There are some Thymeleaf properties you should know about in this HTML:<\/p>\n<ul class=\"wp-block-list\">\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@{\/logout}<\/code>&nbsp;&#8211; returns the logout URL defined on the backend<\/li>\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">th:if=\"${#authorization.expression('isAuthenticated()')}\"<\/code>&nbsp;&#8211; only print the HTML if the user is&nbsp;<strong>logged in<\/strong><\/li>\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@{\/\/oauth2\/authorization\/okta}<\/code>&nbsp;&#8211; this is the URL that Spring Security redirects to for Okta. You could link to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/login<\/code>as well, but that just renders the same link and you have to click on it.<\/li>\n<li><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">th:unless=\"${#authorization.expression('isAuthenticated()')}\"<\/code>&nbsp;&#8211; only print the HTML inside the node if the user is&nbsp;<strong>logged off<\/strong><\/li>\n<\/ul>\n<p>Now restart the configuration project and school-ui again. If you navigate to typing&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:8080<\/code>, you should see the following screen:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"466\" height=\"173\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/school-ui-loggedin.png\" alt=\"Spring Microservices\" class=\"wp-image-90308\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/school-ui-loggedin.png 466w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/school-ui-loggedin-300x111.png 300w\" sizes=\"(max-width: 466px) 100vw, 466px\" \/><\/figure>\n<\/div>\n<p>After logged in, the screen should appear like this one:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"457\" height=\"254\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/school-ui-loggedoff.png\" alt=\"Spring Microservices\" class=\"wp-image-90309\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/school-ui-loggedoff.png 457w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/school-ui-loggedoff-300x167.png 300w\" sizes=\"(max-width: 457px) 100vw, 457px\" \/><\/figure>\n<\/div>\n<p>Congratulations, you created a microservices architecture using Spring Cloud config and Eureka for service discovery! Now, let\u2019s go one step further and Dockerize every service.<\/p>\n<h2 class=\"wp-block-heading\" id=\"use-docker-to-package-your-spring-apps\">Use Docker to Package Your Spring Apps<\/h2>\n<p><a href=\"https:\/\/www.docker.com\/\">Docker<\/a>&nbsp;is a marvelous technology that allows creating system images similar to&nbsp;<em>Virtual Machines<\/em>&nbsp;but that shares the same Kernel of the host operating system. This feature increases system performance and startup time. Also, Docker provided an ingenious built system that guarantees once an image is created; it won\u2019t be changed, ever. In other words: no more \u201cit works on my machine!\u201d<\/p>\n<p><strong>TIP:<\/strong>&nbsp;Need a deeper Docker background? Have a look at our&nbsp;<a href=\"https:\/\/developer.okta.com\/blog\/2017\/05\/10\/developers-guide-to-docker-part-1?utm_campaign=text_website_all_multiple_dev_ciam_spring-microservices-dockerize_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Developer\u2019s Guide To Docker<\/a>.<\/p>\n<p>You\u2019ll need to create one Docker image for each project. Each image should have the same Maven configuration and&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Dockerfile<\/code>&nbsp;content in the root folder of each project (e.g.,&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui\/Dockerfile<\/code>).<\/p>\n<p>In each project\u2019s pom, add the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">dockerfile-maven-plugin<\/code>:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:xml\">&lt;plugins&gt;\n    ...\n    &lt;plugin&gt;\n        &lt;groupId&gt;com.spotify&lt;\/groupId&gt;\n        &lt;artifactId&gt;dockerfile-maven-plugin&lt;\/artifactId&gt;\n        &lt;version&gt;1.4.9&lt;\/version&gt;\n        &lt;executions&gt;\n            &lt;execution&gt;\n                &lt;id&gt;default&lt;\/id&gt;\n                &lt;goals&gt;\n                    &lt;goal&gt;build&lt;\/goal&gt;\n                    &lt;goal&gt;push&lt;\/goal&gt;\n                &lt;\/goals&gt;\n            &lt;\/execution&gt;\n        &lt;\/executions&gt;\n        &lt;configuration&gt;\n            &lt;repository&gt;developer.okta.com\/microservice-docker-${project.artifactId}&lt;\/repository&gt;\n            &lt;tag&gt;${project.version}&lt;\/tag&gt;\n            &lt;buildArgs&gt;\n                &lt;JAR_FILE&gt;${project.build.finalName}.jar&lt;\/JAR_FILE&gt;\n            &lt;\/buildArgs&gt;\n        &lt;\/configuration&gt;\n    &lt;\/plugin&gt;\n&lt;\/plugins&gt;\n<\/pre>\n<p>This XML configures the&nbsp;<a href=\"https:\/\/github.com\/spotify\/dockerfile-maven\">Dockerfile Maven<\/a>&nbsp;plugin to build a Docker image every time you run&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.\/mvnw install<\/code>. Each image will be created with the name&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">developer.okta.com\/microservice-docker-${project.artifactId}<\/code>&nbsp;where&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">project.artifactId<\/code>&nbsp;varies by project.<\/p>\n<p>Create a&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Dockerfile<\/code>&nbsp;file in the root directory of each project.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:sql\">FROM openjdk:8-jdk-alpine\nVOLUME \/tmp\nADD target\/*.jar app.jar\nENV JAVA_OPTS=\"\nENTRYPOINT [ \"sh\", \"-c\", \"java $JAVA_OPTS -Djava.security.egd=file:\/dev\/.\/urandom -jar \/app.jar\"<\/pre>\n<p>The<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Dockerfile<\/code>&nbsp;follows what is recommended by&nbsp;<a href=\"https:\/\/spring.io\/guides\/gs\/spring-boot-docker\/\">Spring Boot with Docker<\/a>.<\/p>\n<p>Now, change&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui\/src\/main\/resources\/bootstrap.yml<\/code>&nbsp;to add a new&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">failFast<\/code>&nbsp;setting:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">eureka:\n  client:\n    serviceUrl:\n      defaultZone: ${EUREKA_SERVER:http:\/\/localhost:8761\/eureka}\nspring:\n  application:\n    name: school-ui\n  cloud:\n    config:\n      discovery:\n        enabled: true\n        serviceId: CONFIGSERVER\n      failFast: true<\/pre>\n<p>The&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">spring.cloud.failFast: true<\/code>&nbsp;setting tells Spring Cloud Config to terminate the application as soon as it can\u2019t find the configuration server. This will be useful for the next step.<\/p>\n<h3 class=\"wp-block-heading\" id=\"add-docker-compose-to-run-everything\">Add Docker Compose to Run Everything<\/h3>\n<p>Create a new file called&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">docker-compose.yml<\/code>&nbsp;that defines how each project starts:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">version: '3'\nservices:\n  discovery:\n    image: developer.okta.com\/microservice-docker-discovery:0.0.1-SNAPSHOT\n    ports:\n      - 8761:8761\n  config:\n    image: developer.okta.com\/microservice-docker-config:0.0.1-SNAPSHOT\n    volumes:\n      - .\/config-data:\/var\/config-data\n    environment:\n      - JAVA_OPTS=\n         -DEUREKA_SERVER=http:\/\/discovery:8761\/eureka\n         -Dspring.cloud.config.server.native.searchLocations=\/var\/config-data\n    depends_on:\n      - discovery\n    ports:\n      - 8888:8888\n  school-service:\n    image: developer.okta.com\/microservice-docker-school-service:0.0.1-SNAPSHOT\n    environment:\n      - JAVA_OPTS=\n        -DEUREKA_SERVER=http:\/\/discovery:8761\/eureka\n    depends_on:\n      - discovery\n      - config\n  school-ui:\n    image: developer.okta.com\/microservice-docker-school-ui:0.0.1-SNAPSHOT\n    environment:\n      - JAVA_OPTS=\n        -DEUREKA_SERVER=http:\/\/discovery:8761\/eureka\n    restart: on-failure\n    depends_on:\n      - discovery\n      - config\n    ports:\n      - 8080:8080<\/pre>\n<p>As you can see, each project is now a declared service in Docker compose the file. It\u2019ll have its ports exposed and some other properties.<\/p>\n<ul class=\"wp-block-list\">\n<li>All projects besides&nbsp;<em>discovery<\/em>&nbsp;will have a variable value&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">-DEUREKA_SERVER=http:\/\/discovery:8761\/eureka<\/code>. This will tell where to find the Discovery server. Docker Compose creates a virtual network between the services and the DNS name used for each service is its name: that\u2019s why it\u2019s possible to use&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">discovery<\/code>&nbsp;as the hostname.<\/li>\n<li>The Config service will have a volume going to configuration files. This volume will be mapped to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/var\/config-data<\/code>inside the docker container. Also, the property&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">spring.cloud.config.server.native.searchLocations<\/code>&nbsp;will be overwritten to the same value. You must store the file&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui.properties<\/code>&nbsp;in the same folder specified on the volume mapping (in the example above, the&nbsp;<em>relative<\/em>&nbsp;folder&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.\/config-data<\/code>).<\/li>\n<li>The&nbsp;<em>school-ui<\/em>&nbsp;project will have the property&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">restart: on-failure<\/code>. This set Docker Compose to restart the application as soon as it fails. Using together with&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">failFast<\/code>&nbsp;property allows the application to keep trying to start until the&nbsp;<em>Discovery<\/em>&nbsp;and&nbsp;<em>Config<\/em>&nbsp;projects are completely ready.<\/li>\n<\/ul>\n<p>And that\u2019s it! Now, build the images:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">cd config &amp;&amp; .\/mvnw clean install\ncd ..\/discovery &amp;&amp; .\/mvnw clean install\ncd .. &amp;&amp; .\/mvnw clean install<\/pre>\n<p>The last command will likely fail with the following error in the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui<\/code>&nbsp;project:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">java.lang.IllegalStateException: Failed to load ApplicationContext\nCaused by: java.lang.IllegalStateException: No instances found of configserver (CONFIGSERVER)<\/pre>\n<p>To fix this, create a&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui\/src\/test\/resources\/test.properties<\/code>&nbsp;file and add properties so Okta\u2019s config passes, and it doesn\u2019t use discovery or the config server when testing.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">okta.oauth2.issuer=https:\/\/{yourOktaDomain}\/oauth2\/default\nokta.oauth2.clientId=TEST\nspring.cloud.discovery.enabled=false\nspring.cloud.config.discovery.enabled = false\nspring.cloud.config.enabled = false<\/pre>\n<p>Then modify&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">UIWebApplicationTests.java<\/code>&nbsp;to load this file for test properties:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">import org.springframework.test.context.TestPropertySource;\n\n...\n@TestPropertySource(locations=\"classpath:test.properties\")\npublic class UIWebApplicationTests {\n    ...\n}<\/pre>\n<p>Now you should be able to run&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.\/mvnw clean install<\/code>&nbsp;in the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui<\/code>&nbsp;project.<\/p>\n<p>Once that completes, run Docker Compose to start all your containers (in the same directory where&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">docker-compose.yml<\/code>&nbsp;is).<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">docker-compose up -d\nStarting okta-microservice-docker-post-final_discovery_1 ... done\nStarting okta-microservice-docker-post-final_config_1    ... done\nStarting okta-microservice-docker-post-final_school-ui_1      ... done\nStarting okta-microservice-docker-post-final_school-service_1 ... done<\/pre>\n<p>Now you should be able to browse the application as you did previously.<\/p>\n<h2 class=\"wp-block-heading\" id=\"use-spring-profiles-to-modify-your-microservices-configuration\">Use Spring Profiles to Modify Your Microservices\u2019 Configuration<\/h2>\n<p>Now you\u2019ve reached the last stage of today\u2019s journey through microservices.&nbsp;<a href=\"https:\/\/docs.spring.io\/spring-boot\/docs\/current\/reference\/html\/boot-features-profiles.html\">Spring Profiles<\/a>&nbsp;is a powerful tool. Using profiles, it is possible to modify program behavior by injecting different dependencies or configurations completely.<\/p>\n<p>Imagine you have a well-architected software that has its persistence layer separated from business logic. You also provide support for MySQL and PostgreSQL, for example. It is possible to have different data access classes for each database that will be only loaded by the defined profile.<\/p>\n<p>Another use case is for configuration: different profiles might have different configurations. Take authentication, for instance. Will your test environment have authentication? If it does, it shouldn\u2019t use the same user directory as production.<\/p>\n<p>Change your configuration project to have two apps in Okta: one default (for development) and another for production. Create a new Web application on Okta website and name it \u201cokta-docker-production.\u201d<\/p>\n<p>Now, in your&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">config<\/code>&nbsp;project, create a new file called&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui-production.properties<\/code>. You already have&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui.properties<\/code>, which will be used by every School UI instance. When adding the environment at the end of the file, Spring will merge both files and take precedence over the most specific file. Save the file with your production app\u2019s client ID and secret, like this:<\/p>\n<p><strong>school-ui-production.properties<\/strong><\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">okta.oauth2.clientId={YOUR_PRODUCTION_CLIENT_ID}\nokta.oauth2.clientSecret={YOUR_PRODUCTION_CLIENT_SECRET}<\/pre>\n<p>Now, run the configuration project using Maven, then run the following two&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">curl<\/code>&nbsp;commands:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">.\/mvnw spring-boot:run\n\n&gt; curl http:\/\/localhost:8888\/school-ui.properties\n\nokta.oauth2.issuer: https:\/\/{yourOktaDomain}\/oauth2\/default\nokta.oauth2.clientId: ==YOUR DEV CLIENT ID HERE==\nokta.oauth2.clientSecret: ==YOUR DEV CLIENT SECRET HERE==\n\n&gt; curl http:\/\/localhost:8888\/school-ui-production.properties\nokta.oauth2.issuer: https:\/\/{yourOktaDomain}\/oauth2\/default\nokta.oauth2.clientId: ==YOUR PROD CLIENT ID HERE==\nokta.oauth2.clientSecret: ==YOUR PROD CLIENT SECRET HERE==<\/pre>\n<p>As you can see, even though the file&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui-production<\/code>&nbsp;has two properties, the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">config<\/code>&nbsp;project displays three (since the configurations are merged).<\/p>\n<p>Now, you can change the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui<\/code>&nbsp;service in the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">docker-compose.yml<\/code>&nbsp;to use the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">production<\/code>&nbsp;profile:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">school-ui:\n  image: developer.okta.com\/microservice-docker-school-ui:0.0.1-SNAPSHOT\n  environment:\n    - JAVA_OPTS=\n      -DEUREKA_SERVER=http:\/\/discovery:8761\/eureka\n      -Dspring.profiles.active=production\n  restart: on-failure\n  depends_on:\n    - discovery\n    - config\n  ports:\n    - 8080:8080<\/pre>\n<p>You\u2019ll also need to copy&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui-production.properties<\/code>&nbsp;to your&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">config-data<\/code>&nbsp;directory. Then shut down all your Docker containers and restart them.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">docker-compose down\ndocker-compose up -d<\/pre>\n<p>You should see the following printed in the logs of the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">school-ui<\/code>&nbsp;container:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">The following profiles are active: production<\/pre>\n<p>That\u2019s it! Now you have your microservices architecture running with a production profile. Huzzah!<\/p>\n<p><strong>TIP:<\/strong>&nbsp;If you want to prove your&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">okta-docker-production<\/code>&nbsp;app is used and not&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">okta-docker<\/code>, you can deactivate the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">okta-docker<\/code>&nbsp;app in Okta and confirm you can still log in at&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http:\/\/localhost:8080<\/code>.<\/p>\n<h2 class=\"wp-block-heading\" id=\"learn-more-about-microservices-spring-docker-and-modern-application-security\">Learn More About Microservices, Spring, Docker, and Modern Application Security<\/h2>\n<p>In this post, you learned more about microservices and how to deploy them, along with:<\/p>\n<ul class=\"wp-block-list\">\n<li>What is a microservice?<\/li>\n<li>How services should discover its dependencies without previously knowing where they are located.<\/li>\n<li>How to maintain distributed configuration with a central point of information. The configuration can manage one or more applications and environments.<\/li>\n<li>How to configure OAuth 2.0 using Spring Cloud Config.<\/li>\n<li>How to deploy microservices using Docker and Docker Compose.<\/li>\n<li>How to use Spring Profiles to deploy in a production environment.<\/li>\n<\/ul>\n<p>You can find the completed source code for this tutorial on GitHub at&nbsp;<a href=\"https:\/\/github.com\/oktadeveloper\/okta-spring-microservices-docker-example\">oktadeveloper\/okta-spring-microservices-docker-example<\/a>.<\/p>\n<p>If you\u2019re interested in learning more about microservices, or modern application development in Spring, I encourage you to check out these resources:<\/p>\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2018\/05\/17\/microservices-spring-boot-2-oauth?utm_campaign=text_website_all_multiple_dev_ciam_spring-microservices-dockerize_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Build and Secure Microservices with Spring Boot 2.0 and OAuth 2.0<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2018\/03\/01\/develop-microservices-jhipster-oauth?utm_campaign=text_website_all_multiple_dev_ciam_spring-microservices-dockerize_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Developer a Microservices Architecture with JHipster and OAuth 2.0<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2017\/06\/15\/build-microservices-architecture-spring-boot?utm_campaign=text_website_all_multiple_dev_ciam_spring-microservices-dockerize_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Build a Microservices Architecture for Microbrews with Spring Boot<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2018\/11\/26\/spring-boot-2-dot-1-oidc-oauth2-reactive-apis?utm_campaign=text_website_all_multiple_dev_ciam_spring-microservices-dockerize_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Spring Boot 2.1: Outstanding OIDC, OAuth 2.0, and Reactive API Support<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb?utm_campaign=text_website_all_multiple_dev_ciam_spring-microservices-dockerize_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Build a Reactive App with Spring Boot and MongoDB<\/a><\/li>\n<\/ul>\n<p>If you have any questions about this post, please leave a comment below. You can&nbsp;<a href=\"https:\/\/twitter.com\/oktadev\">follow @oktadev on Twitter<\/a>&nbsp;for more awesome content!<\/p>\n<p><a href=\"https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker?utm_campaign=text_website_all_multiple_dev_ciam_spring-microservices-dockerize_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Build Spring Microservices and Dockerize Them for Production&#8221;<\/a>&nbsp;was originally published on the Okta developer blog on February 28, 2019.<\/p>\n<p><span style=\"font-size: 20px;\"><b>\u201cI love writing authentication and authorization code.\u201d ~ No Java Developer Ever.<\/b> Tired of building the same login screens over and over? <a href=\"https:\/\/developer.okta.com\/signup\/?utm_campaign=text_website_all_multiple_dev_ciam_spring-microservices-dockerize_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Try the Okta API for hosted authentication, authorization, and multi-factor auth.<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u201cI love writing authentication and authorization code.\u201d ~ No Java Developer Ever. Tired of building the same login screens over and over? Try the Okta API for hosted authentication, authorization, and multi-factor auth. In this post, you\u2019ll learn about microservices architecture and how to implement it using Spring Boot. After creating some projects with the &hellip;<\/p>\n","protected":false},"author":70622,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[936,960,30,854],"class_list":["post-90296","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-docker","tag-microservices","tag-spring","tag-spring-boot"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Build Spring Microservices and Dockerize Them for Production - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Interested to learn about Spring Microservices? Check our article explaining about microservices architecture and how to implement it using Spring Boot.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Build Spring Microservices and Dockerize Them for Production - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Interested to learn about Spring Microservices? Check our article explaining about microservices architecture and how to implement it using Spring Boot.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2019-04-01T16:44:31+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-04-08T06:11:11+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Raphael Do_vale\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Raphael Do_vale\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"28 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/28\\\/spring-microservices-docker#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/build-spring-microservices-dockerize-production.html\"},\"author\":{\"name\":\"Raphael Do_vale\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/2d25326ca456ba29bdebf6c24fda4213\"},\"headline\":\"Build Spring Microservices and Dockerize Them for Production\",\"datePublished\":\"2019-04-01T16:44:31+00:00\",\"dateModified\":\"2019-04-08T06:11:11+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/build-spring-microservices-dockerize-production.html\"},\"wordCount\":3591,\"commentCount\":6,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/28\\\/spring-microservices-docker#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"Docker\",\"Microservices\",\"Spring\",\"Spring Boot\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/28\\\/spring-microservices-docker#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/build-spring-microservices-dockerize-production.html\",\"url\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/28\\\/spring-microservices-docker\",\"name\":\"Build Spring Microservices and Dockerize Them for Production - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/28\\\/spring-microservices-docker#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/28\\\/spring-microservices-docker#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2019-04-01T16:44:31+00:00\",\"dateModified\":\"2019-04-08T06:11:11+00:00\",\"description\":\"Interested to learn about Spring Microservices? Check our article explaining about microservices architecture and how to implement it using Spring Boot.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/28\\\/spring-microservices-docker#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/28\\\/spring-microservices-docker\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/28\\\/spring-microservices-docker#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/28\\\/spring-microservices-docker#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Build Spring Microservices and Dockerize Them for Production\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/2d25326ca456ba29bdebf6c24fda4213\",\"name\":\"Raphael Do_vale\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/576a053f49ea5125f5cf78cafd67379057e740a9b1e301abdbf3130243c37f26?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/576a053f49ea5125f5cf78cafd67379057e740a9b1e301abdbf3130243c37f26?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/576a053f49ea5125f5cf78cafd67379057e740a9b1e301abdbf3130243c37f26?s=96&d=mm&r=g\",\"caption\":\"Raphael Do_vale\"},\"sameAs\":[\"https:\\\/\\\/developer.okta.com\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/raphael-do_vale\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Build Spring Microservices and Dockerize Them for Production - Java Code Geeks","description":"Interested to learn about Spring Microservices? Check our article explaining about microservices architecture and how to implement it using Spring Boot.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker","og_locale":"en_US","og_type":"article","og_title":"Build Spring Microservices and Dockerize Them for Production - Java Code Geeks","og_description":"Interested to learn about Spring Microservices? Check our article explaining about microservices architecture and how to implement it using Spring Boot.","og_url":"https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2019-04-01T16:44:31+00:00","article_modified_time":"2019-04-08T06:11:11+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Raphael Do_vale","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Raphael Do_vale","Est. reading time":"28 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/04\/build-spring-microservices-dockerize-production.html"},"author":{"name":"Raphael Do_vale","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/2d25326ca456ba29bdebf6c24fda4213"},"headline":"Build Spring Microservices and Dockerize Them for Production","datePublished":"2019-04-01T16:44:31+00:00","dateModified":"2019-04-08T06:11:11+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/04\/build-spring-microservices-dockerize-production.html"},"wordCount":3591,"commentCount":6,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["Docker","Microservices","Spring","Spring Boot"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2019\/04\/build-spring-microservices-dockerize-production.html","url":"https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker","name":"Build Spring Microservices and Dockerize Them for Production - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker#primaryimage"},"image":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2019-04-01T16:44:31+00:00","dateModified":"2019-04-08T06:11:11+00:00","description":"Interested to learn about Spring Microservices? Check our article explaining about microservices architecture and how to implement it using Spring Boot.","breadcrumb":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/developer.okta.com\/blog\/2019\/02\/28\/spring-microservices-docker#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Build Spring Microservices and Dockerize Them for Production"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/2d25326ca456ba29bdebf6c24fda4213","name":"Raphael Do_vale","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/576a053f49ea5125f5cf78cafd67379057e740a9b1e301abdbf3130243c37f26?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/576a053f49ea5125f5cf78cafd67379057e740a9b1e301abdbf3130243c37f26?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/576a053f49ea5125f5cf78cafd67379057e740a9b1e301abdbf3130243c37f26?s=96&d=mm&r=g","caption":"Raphael Do_vale"},"sameAs":["https:\/\/developer.okta.com"],"url":"https:\/\/www.javacodegeeks.com\/author\/raphael-do_vale"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/90296","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/70622"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=90296"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/90296\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=90296"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=90296"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=90296"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}