1

I'm new to Spring and Docker.

I created a project by using the default template provided by Gitlab. It comes with a predefined Dockerfile on which I would like to add some extra environment variables to be used inside my application.properties.

What I've done so far is adding the MY_PROP ENV value inside the DockerFile like this:

FROM maven:3-jdk-8-alpine

WORKDIR /usr/src/app

COPY . /usr/src/app
RUN mvn package

ENV PORT 5000
ENV MY_PROP testpropertyfromdocker
EXPOSE $PORT
CMD [ "sh", "-c", "mvn -Dserver.port=${PORT} spring-boot:run" ]

Set my application.properties like this:

test.prop=${MY_PROP}

And try to use it in a basic RestControntroller:

@SpringBootApplication
@RestController
public class DemoApplication {

    @Value("${test.prop}")
    private String testProp;

    @GetMapping("/")
    String home() {
        return "My prop from docker: " + testProp;
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

But if I try to build my Docker image with

docker build -t demo .

It fails on

java.lang.IllegalArgumentException: Could not resolve placeholder 'MY_PROP' in value "${MY_PROP}"

I've also tried to run the project directly in IntelliJ without building the Docker image but got the same error even when adding a .env file.

How do I pass my environment variable to my Spring application ? Is it possible to have a .env file or similar to use when debugging inside the IDE or do I have to build the image to be able to run the project ?

PS: I don't think this is a duplicate of Externalising Spring Boot properties when deploying to Docker or at least the answer should be more complete as I didn't manage to have my configuration working as expected.

EDIT I updated my pom.xml to include this:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.2.2.RELEASE</version>
            <configuration>
                <environmentVariables>
                    <MY_PROP>testfromappprops</MY_PROP>
                </environmentVariables>
            </configuration>
        </plugin>
    </plugins>
</build>  

I made a clean and build and resync maven project but it is still failing even when running through the IDE.

EDIT 2 I update dmy DockerFile to use java -jar:

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENV MY_PROP testpropertyfromdocker
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

The docker build -t demo . command line is working but the docker run demo is giving the following output:

Error: Invalid or corrupt jarfile /app.jar

Also, when running from the IDE (the "run" button), I still have same error about environment variable not found.

Thanks.

MHogge
  • 5,408
  • 15
  • 61
  • 104

2 Answers2

1

I think its something related to the way you run the application.

Since you're new to spring boot, lets eliminate wrong/confirm some parts of your code:

  1. @Value("${test.prop}") OK
  2. test.prop=${MY_PROP} in application.properties OK, as long as the file is placed in src/main/resources or src/main/resources/config
  3. ENV MY_PROP testpropertyfromdocker in Dockerfile is also OK

Now, what's suspicious in your configuration is the way you actually run the project. Usually mvn package should create a JAR of the docker application (you're supposed to use spring-boot-maven-plugin for that). But when it does so, you should run the artifact with: java -jar <YOUR_ARTIFACT.JAR>

Instead you've opted to run the compiled codebase directly with maven. But if you want to propagate env.variables or system properties in maven plugin you should instruct the plugin to do so:

Here is a section about env variables

Here is a section about system properties

In general this way is more for debugging the application in development than running a ready artifact (prefer the option with java -jar that I've described above).

So I suspect that regardless the environment it runs in (with docker or without, in IDE) as long as you start the application this way, the env. variables are not "available" for use so spring boot merely doesn't see them.

Update 1

To verify this point, make sure that this env. variable is not really accessible, even without spring:

Go to main method of the class annotated with @SpringBootApplication annotation. It usually contains a line of running the application. But even before that try to print the value of that env. variable with System.getenv("MY_PROP")

Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97
  • Thanks for the answer. I've updating my pom.xml (see edit in my original post) but I stil have the same issue. I would like to at least being able to run it from the IDE. I'm not sure on the steps to follow in order to build it by using the artificat of spring-boot like you said? – MHogge Dec 11 '19 at 08:55
  • I've updated my answer and offered a way to verify this hypothesis – Mark Bramnik Dec 11 '19 at 09:01
  • You're right the `System.getenv("MY_PROP")` returns null. So this is a Spring config issue? Any hint on why I can't reach my env variables ? (I'm searching on the net in meantime). – MHogge Dec 11 '19 at 09:07
  • No, its not spring config issue, its an issue of propagating env. variables through spring-boot-maven-plugin when you execute spring-boot:run goal – Mark Bramnik Dec 11 '19 at 09:11
  • https://www.baeldung.com/spring-boot-command-line-arguments Please, read and try to propagate a value of MY_PROPS this way... – Mark Bramnik Dec 11 '19 at 09:12
  • Ok so I've run `mvn spring-boot:run -Dspring-boot.run.arguments=--spring.main.banner-mode=off,--MY_PROP=fromcmdline` and it printed "testfromappprops" when passing through the `main`method (before running application) and printed "fromcmdline" when I've been to the REST endpoint. It has taken the .env variable from the `pom.xml` before running the application and then overwrite it with the one from the cmd line. – MHogge Dec 11 '19 at 09:17
  • Ok, so the reason of error is found :) Now try to run with java -jar from docker and you should be ok.... – Mark Bramnik Dec 11 '19 at 09:20
  • Not sure how to proceed but I've tried to update my DockerFile and got a "Error: Invalid or corrupt jarfile /app.jar" error when running docker run. You can see my edit in the original post. – MHogge Dec 11 '19 at 10:01
  • @MHogge you're not pasing args while `docker build`, I don't think the `ARG JAR_FILE` is resolved here. – Shubham Dec 11 '19 at 10:05
  • But this returns to the main issue: when I'm running `mvnw package && java -jar target/demo-spring.jar` I facing the "Could not resolve MY_PROP" error. – MHogge Dec 11 '19 at 10:15
  • If the jar is corrupted, the chances are that its nit processed by speing boot maven plugin correctly. Make sure that you can run with java -jar without any docker – Mark Bramnik Dec 11 '19 at 16:52
0

i think the application.properties for the app must be complete , as the log says your application cant read the docker file .

once you have the application.properties properly defined you can run :

$ docker run -e "SPRING_PROFILES_ACTIVE=prod" -p 8080:8080 -t springio/gs-spring-boot-docker

A useful guide is here

solocoding
  • 81
  • 1
  • 3
  • Not sure what you're talking about when saying "the application.prop for the app must be complete". Is it referring do the `application.properties` file ? If yes, how isn't it complete? – MHogge Dec 11 '19 at 08:31
  • yes i meant application.properties, i am not sure u can refrence the docker file or some of his props in the application.properties – solocoding Dec 11 '19 at 08:36