Victoria Agafonova
Victoria Agafonova

Reputation: 2178

The best way to make app configs editable for docker image/container?

I have an app which is dockerized like this:

FROM openjdk:11-jre-slim as jdkbase

FROM jdkbase
COPY target/dependency-jars /run/dependency-jars
COPY target/resources /run/resources
ADD target/app-1.0.2.jar /run/app-1.0.2.jar

CMD java -jar run/app-1.0.2.jar

This app uses some configs from application.properties. I push this docker image into my private registry for using it inside Kubernetes cluster.

There is no problems unless i have to change any properties in application.properties. Lets say, my database URL was changed. So, I have to undate it in application.properties and then force my app to use updated configs. I've tried to edit application.properties inside the running docker container and then restart the container. As a result, after i restart my container it has edited application.properties BUT the app still uses old URL. The only way i've found to force the app to use new configs is to commit changed container into new image and then start the new image.

It works, but it doesn't seems to me to be an optimal solution: like, after every changes in app's configs I have to recreate image, which is +300Mb of data, I have to push this new image into registry, I have to recreate Kubernetes pod from new image... It looks like too much unnecessary actions to just change one URL.

So, is there any other more optimal way to work with needs to change application.properties from time to time?

Upvotes: 0

Views: 340

Answers (1)

Davide Lorenzo MARINO
Davide Lorenzo MARINO

Reputation: 26956

If this is a spring boot application is easy to define a variable as an environment variable. If an environment variable is present it overwrite the variable with the same name defined in your application.properties.

What happens is called externalized configuration and it is defined here :

Spring Boot allows you to externalize your configuration so you can work with the same application code in different environments. You can use properties files, YAML files, environment variables and command-line arguments to externalize configuration. Property values can be injected directly into your beans using the @Value annotation, accessed via Spring’s Environment abstraction or bound to structured objects via @ConfigurationProperties. Spring Boot uses a very particular PropertySource order that is designed to allow sensible overriding of values. Properties are considered in the following order:

  • Devtools global settings properties on your home directory (~/.spring-boot-devtools.properties when devtools is active).
  • @TestPropertySource annotations on your tests.
  • @SpringBootTest#properties annotation attribute on your tests.
  • Command line arguments.
  • Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property)
  • ServletConfig init parameters.
  • ServletContext init parameters.
  • JNDI attributes from java:comp/env.
  • Java System properties (System.getProperties()).
  • OS environment variables.
  • A RandomValuePropertySource that only has properties in random.*.
  • Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants)
  • Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants)
  • Application properties outside of your packaged jar (application.properties and YAML variants).
  • Application properties packaged inside your jar (application.properties and YAML variants).
  • @PropertySource annotations on your @Configuration classes. Default properties (specified using SpringApplication.setDefaultProperties).

So you can pass at runtime an environment variable to your docker to solve this problem. You don't need to recreate the Docker image each time.

Upvotes: 1

Related Questions