<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gabriel Dinant</title>
    <description>The latest articles on DEV Community by Gabriel Dinant (@gdinant_migrosonline).</description>
    <link>https://dev.to/gdinant_migrosonline</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3208507%2F5cfa16cf-2b17-40e9-944f-cdc611e7be64.jpg</url>
      <title>DEV Community: Gabriel Dinant</title>
      <link>https://dev.to/gdinant_migrosonline</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gdinant_migrosonline"/>
    <language>en</language>
    <item>
      <title>How to run services locally with no fuss using spring-boot-docker-compose</title>
      <dc:creator>Gabriel Dinant</dc:creator>
      <pubDate>Tue, 02 Sep 2025 05:42:28 +0000</pubDate>
      <link>https://dev.to/migrosonline/how-to-run-services-locally-with-no-fuss-using-spring-boot-docker-compose-4nhb</link>
      <guid>https://dev.to/migrosonline/how-to-run-services-locally-with-no-fuss-using-spring-boot-docker-compose-4nhb</guid>
      <description>&lt;p&gt;Running services locally hasn't always been easy and still has its quirks. As soon as a service is integrated with external systems it can become challenging.&lt;/p&gt;

&lt;p&gt;In this blog post, we will walk through how to set up a Spring Boot application that connects to multiple systems such as a message broker or a database, while using &lt;code&gt;spring-boot-docker-compose&lt;/code&gt; to manage these dependencies as part of the application lifecycle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why &amp;amp; When to consider?
&lt;/h2&gt;

&lt;p&gt;Using live environments during development has its own set of pros &amp;amp; cons. &lt;/p&gt;

&lt;p&gt;✅ Common technologies supported by Spring Boot / Spring Cloud such as Kafka, MySQL, Firebase, RabbitMQ, and so on, are technologies that can and should be substituted whenever possible.&lt;/p&gt;

&lt;p&gt;⚠️ On the flip side, mocking the behaviour of upstream services introduces complexity and should be carefully considered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use case
&lt;/h2&gt;

&lt;p&gt;Consider a &lt;code&gt;Blog Application&lt;/code&gt; that &lt;em&gt;consumes&lt;/em&gt; &lt;code&gt;Kafka&lt;/code&gt; events from a topic (&lt;code&gt;blog.updates&lt;/code&gt;), calculates the sentiment of the given blogpost and pushes the final update in a RabbitMQ queue. For this exercise, let's pretend the publisher is also the consumer and eventually &lt;em&gt;saves&lt;/em&gt; the processed result in a &lt;code&gt;MSSQL server&lt;/code&gt; database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qgwjvwq9urcegk5w8vr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qgwjvwq9urcegk5w8vr.png" alt="Architecture" width="800" height="599"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Let's take a look at the complete picture of the project before diving into each part.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── pom.xml 👈🏻
└── src
    ├── main
    │   ├── java
    │   │   └── ch
    │   │       └── migrosonline
    │   │           └── blog
    │   │               ├── BlogApplication.java
    │   │               ├── context
    │   │               │   └── RabbitMQContext.java
    │   │               ├── kafka
    │   │               │   ├── BlogPostUpdateEventListener.java
    │   │               │   └── model
    │   │               │       └── BlogPostUpdateEvent.java
    │   │               ├── processor
    │   │               │   └── BlogProcessor.java
    │   │               ├── rabbitmq
    │   │               │   ├── model
    │   │               │   │   └── ProcessedBlogPostMessage.java
    │   │               │   ├── RabbitMQListener.java
    │   │               │   └── RabbitMQProducer.java
    │   │               └── repository
    │   │                   ├── BlogRepository.java
    │   │                   └── model
    │   │                       └── BlogEntity.java
    │   └── resources
    │       ├── application.yml 👈🏻
    │       ├── application-LOCAL.yml 👈🏻
    │       ├── compose.yml 👈🏻
    │       └── init.sql
    └── &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This guide assumes prior familiarity with some bricks of the Spring Ecosystem such as &lt;code&gt;@SpringBootApplication&lt;/code&gt; main class or &lt;code&gt;@Configuration&lt;/code&gt; contexts. What is important to focus on here is the resources marked with a '👈🏻'.&lt;/p&gt;

&lt;h3&gt;
  
  
  pom.xml
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;key&lt;/strong&gt; dependency that must be added to the dependency management system is &lt;code&gt;spring-boot-docker-compose&lt;/code&gt;. Any important details regarding &lt;code&gt;spring-boot-docker-compose&lt;/code&gt; can be found on the &lt;a href="https://docs.spring.io/spring-boot/reference/features/dev-services.html#features.dev-services.docker-compose" rel="noopener noreferrer"&gt;Spring reference documentation&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;

    ...

    &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-docker-compose&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;runtime&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;optional&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/optional&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;

    ...

&lt;span class="nt"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;build&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;plugins&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-maven-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;executions&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;execution&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;goals&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;goal&amp;gt;&lt;/span&gt;repackage&lt;span class="nt"&gt;&amp;lt;/goal&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/goals&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/execution&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/executions&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;/plugins&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/build&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;spring-boot-docker-compose&lt;/code&gt; is primarily a &lt;em&gt;dev tool&lt;/em&gt; therefore  Spring Boot won't be adding this dependency as part of the repackaged application (fat .jar). In other words, it won't be available in production builds unless explicitly &lt;a href="https://docs.spring.io/spring-boot/reference/features/dev-services.html#features.dev-services.docker-compose" rel="noopener noreferrer"&gt;specified&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When starting the application locally via IDE's plugins or the Spring Boot plugin, all runtime dependencies will be available on the classpath.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./mvnw spring-boot:run &lt;span class="nt"&gt;-Dspring-boot&lt;/span&gt;.run.jvmArguments&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-Dspring.profiles.active=LOCAL"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Application properties
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;application.yml&lt;/code&gt; file provides the default, production-grade configuration. By using Spring profiles, we can later define a &lt;code&gt;LOCAL&lt;/code&gt; profile that overrides and leverages the &lt;code&gt;compose.yml&lt;/code&gt; definition.&lt;/p&gt;

&lt;h4&gt;
  
  
  application.yml
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;spring&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;application&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;blog&lt;/span&gt;

  &lt;span class="na"&gt;datasource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;URI_TO_A_REMOTE_DATABASE&amp;gt;&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SA&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${DATABASE_PASSWORD}&lt;/span&gt;

  &lt;span class="na"&gt;docker.compose.enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

  &lt;span class="na"&gt;kafka&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;bootstrap-servers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;URI_TO_A_REMOTE_KAFKA_SERVER&amp;gt;&lt;/span&gt;

    &lt;span class="na"&gt;consumer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;group-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ch.migrosonline&lt;/span&gt;
      &lt;span class="na"&gt;key-deserializer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;org.apache.kafka.common.serialization.StringDeserializer&lt;/span&gt;
      &lt;span class="na"&gt;properties.spring.json.type.mapping&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;blogpost-update-event:ch.migrosonline.momentum.kafka.model.BlogPostUpdateEvent&lt;/span&gt;

    &lt;span class="na"&gt;security&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SASL_SSL&lt;/span&gt;
      &lt;span class="na"&gt;properties.sasl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;mechanism&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PLAIN&lt;/span&gt;
        &lt;span class="na"&gt;jaas.config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;org.apache.kafka.common.security.plain.PlainLoginModule required username='kafka' password='${KAFKA_PASSWORD}'&lt;/span&gt;

  &lt;span class="na"&gt;rabbitmq&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;URI_TO_A_REMOTE_RABBITMQ_SERVER&amp;gt;&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5672&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rabbitmq&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${RABBIT_PASSWORD}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  application-LOCAL.yml
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;spring&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;datasource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jdbc:sqlserver://localhost;encrypt=false&lt;/span&gt;

  &lt;span class="na"&gt;docker.compose&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;classpath:/compose.yml&lt;/span&gt;
    &lt;span class="na"&gt;stop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;down&lt;/span&gt; &lt;span class="c1"&gt;# 'docker compose down' on application stop&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;

  &lt;span class="na"&gt;kafka&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;bootstrap-servers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;localhost:29092&lt;/span&gt;
    &lt;span class="na"&gt;security.protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PLAINTEXT&lt;/span&gt;

  &lt;span class="na"&gt;rabbitmq&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;

  &lt;span class="na"&gt;sql&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;init&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
      &lt;span class="na"&gt;schema-locations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;classpath:init.sql&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, the &lt;code&gt;docker.compose.lifecycle-management&lt;/code&gt; property runs &lt;code&gt;docker compose up&lt;/code&gt; when the application starts and &lt;code&gt;docker compose stop&lt;/code&gt; when it stops. These commands can be customised by redefining the start or stop command as shown in the &lt;code&gt;application-LOCAL.yml&lt;/code&gt; file.&lt;/p&gt;

&lt;h3&gt;
  
  
  compose.yml
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;compose.yml&lt;/code&gt; file is fully customisable and describes services to be substituted. &lt;/p&gt;

&lt;p&gt;In the example below, a Kafka cluster (with a topic and partitions), an MSSQL database service, and a RabbitMQ service are defined.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;kafka&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;confluentinc/cp-kafka:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kafka&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;29092:9094"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;CLUSTER_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clusterId&lt;/span&gt;
      &lt;span class="na"&gt;KAFKA_PROCESS_ROLES&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;broker,controller&lt;/span&gt;
      &lt;span class="na"&gt;KAFKA_NODE_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
      &lt;span class="na"&gt;KAFKA_LISTENERS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094&lt;/span&gt;
      &lt;span class="na"&gt;KAFKA_ADVERTISED_LISTENERS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PLAINTEXT://kafka:9092,EXTERNAL://localhost:29092&lt;/span&gt;
      &lt;span class="na"&gt;KAFKA_LISTENER_SECURITY_PROTOCOL_MAP&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT&lt;/span&gt;
      &lt;span class="na"&gt;KAFKA_CONTROLLER_QUORUM_VOTERS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0@kafka:9093&lt;/span&gt;
      &lt;span class="na"&gt;KAFKA_CONTROLLER_LISTENER_NAMES&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CONTROLLER&lt;/span&gt;
      &lt;span class="na"&gt;KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

  &lt;span class="na"&gt;kafka-initializer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;confluentinc/cp-kafka:latest&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;kafka&lt;/span&gt;
    &lt;span class="na"&gt;entrypoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/bin/sh'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-c'&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;"&lt;/span&gt;
      &lt;span class="s"&gt;kafka-topics --bootstrap-server kafka:9092 --create --if-not-exists --topic blog.updates --partitions 2 --replication-factor 1&lt;/span&gt;
      &lt;span class="s"&gt;kafka-topics --bootstrap-server kafka:9092 --list&lt;/span&gt;
      &lt;span class="s"&gt;"&lt;/span&gt;

  &lt;span class="na"&gt;mssql&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mcr.microsoft.com/mssql/server:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mssql&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1433:1433"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;ACCEPT_EULA&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Y&lt;/span&gt;
      &lt;span class="na"&gt;MSSQL_SA_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${DATABASE_PASSWORD}&lt;/span&gt;

  &lt;span class="na"&gt;rabbitmq&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rabbitmq:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rabbitmq&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5672:5672"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;RABBITMQ_DEFAULT_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rabbitmq&lt;/span&gt;
      &lt;span class="na"&gt;RABBITMQ_DEFAULT_PASS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${RABBIT_PASSWORD}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Alternative approach
&lt;/h2&gt;

&lt;p&gt;Testcontainers is an alternative to substitute external services  not only in tests but also in dev mode. If you are interested to know more you can read the official Spring &lt;a href="https://docs.spring.io/spring-boot/reference/features/dev-services.html#features.dev-services.testcontainers" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We saw how to wire production grade technologies all together in a seamless way with &lt;code&gt;Docker&lt;/code&gt; and &lt;code&gt;spring-boot-docker-compose&lt;/code&gt;, why and when this setup should be considered.&lt;/p&gt;

&lt;p&gt;The full source code can be found ➡️ &lt;a href="https://github.com/gdinant/momentum/tree/main/spring-boot-docker-compose" rel="noopener noreferrer"&gt;here&lt;/a&gt; ⬅️.&lt;/p&gt;

&lt;p&gt;Happy coding! 👨🏻‍💻👩🏼‍💻&lt;/p&gt;




&lt;p&gt;Written by Gabriel Dinant, &lt;a href="https://www.linkedin.com/company/migros-online/posts/?feedView=all" rel="noopener noreferrer"&gt;Staff Software Engineer @ MigrosOnline&lt;/a&gt; &lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
