Read docker env variable inside Spring application.yaml

Viewed 3897

I'm setting an environment variable inside my docker-compose.yaml file and want to use that variable's value inside my Spring Boot's application.yaml. I was told that doing something like

app:
  auth:
    tokenSecret: tokensecretvaluehere
    tokenExpirationMsec: 864000000
  oauth2:
    sso:
      url: ${SSO_URL}

(where SSO_URL is defined in my docker-compose.yaml) in my Spring application.yaml. However, this causes an error when I run docker-compose up --build because it can't find that variable (error is like: Could not resolve placeholder SSO_URL in value "${SSO_URL}"). This is an example of what my docker-compose.yaml:

api:
    restart: always
    ports:
      - "8080:8080"
    links:
      - redis
      - db
    environment:
      - SERVER_SERVLET_SESSION_COOKIE_DOMAIN=localhost
      - SSO_URL=myvaluehere

I was asked to not uses the System.getenv functions in Java and instead set the variable like above. From there I would just use the @Value annotation to get it in my Java code as like below:

@Value("${app.oauth2.sso.url}")
private String ssoUrl;

This is more of the application.yaml:

heb:
  togglr:
    jwt:
      secret:
        id: 101
      session:
        seconds: 600
      tokenheader: X-TOGGLR-TOKEN
logging:
  level:
    com:
      heb: debug
    default: debug
  path: logs
server:
  error:
    whitelabel:
      enabled: false
  port: 8080
  servlet:
    context-path: /togglr-api
  use-forward-headers: true
spring:
  application:
    name: togglr_api
  freemarker:
    enabled: false
  groovy:
    template:
      enabled: false
  jmx:
    enabled: false
  main:
    banner-mode: 'off'
  thymeleaf:
    cache: false
  security:
    oauth2:
      client:
        registration:
          github:
            clientId:
            clientSecret:
            redirectUri: 
            scope:
              - user:email
              - read:user
app:
  auth:
    tokenSecret:
    tokenExpirationMsec: 864000000
  oauth2:
    sso:
      url: ${SSO_URL}
3 Answers

In general spring boot applications are able to read the Environment variables accessible in the docker container. Its stated in the documentation (see item 10 in the list at the very beginning of the document).

So the problem might be elsewhere:

  1. It might be a typo in the question, but if you're using application.yaml as opposed to application properties, then you should have something like:
  sso:
    url: ${SSO_URL}
  1. Make sure, that the env variable SSO_URL is indeed accessible in the container even before you start the spring boot application. In java (for debugging purposes only) you can do something like:
@SpringBootApplication
public class MyApp {
   public static void main(String [] args) {
          System.out.println(System.getenv("SSO_URL"));
          SpringApplication.run(MyApp.class);
   }
}

Solution was to not use an underscore character in the variable name.

I feel what you are missing is the build context within the docker-compose file. Or, you have multiple profile based application.yml and not the correct profile is being set.

Below is the working code / config. So we are creating a springboot application from docker-compose, where docker-compose builds the image of springboot application and passes the required environment variables.

Snippet from Spring application.yml where we are using the env variable named API_BASE and TEST_API_PATH

third-party-api:
  base-url: ${API_BASE}
  test-api-path: ${TEST_API_PATH}

Below is the snippet from docker-compose.yml

 my-app:
    image: my-app-image-name
    build:
      dockerfile: Dockerfile
      context: .
    ports:
      - '9080:8080'
    environment:
      API_BASE: http://mock-api:8080
      TEST_API_PATH: /someTestApiPath
      SPRING_PROFILES_ACTIVE: dev

Docker file of my application is pretty simple.

FROM openjdk:17-alpine
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

Dockerfile and docker-compose.yml are on the same hierarcy, if there is any difference in your structure then it should reflect in below config of docker-compose.yml

build:
   dockerfile: Dockerfile
Related