Roughly speaking, when you build your image under the hood docker creates a series of intermediate containers, one for every line in your Dockerfile.
You are trying to connect from one of this intermediate containers, the one which is packaging your application, to another container running Postgres in your host.
I am not sure if it will work - the subject had been broadly covered here in SO - but, if you are using MacOS or Windows, and your Postgres container exposes the port to the host, you could try modifying the connection string in your Spring properties and use the network address host.docker.internal
to try reaching the database:
# datasource
spring.datasource.url=jdbc:postgresql://host.docker.internal:5432/myApp?currentSchema=gpclinic&createDatabaseIfNotExist=true
spring.datasource.username=uname
spring.datasource.password=pword
You mentioned compose as well, but again I am not sure whether it is possible. Please, see this related SO question.
Having said that, please, be aware that the solution has different drawbacks, among others:
- It makes your docker build not portable, think about building it in Linux or in a CI/CD system.
- Probably you will need to set some kind of Spring profile or similar stuff for dealing with the properties value change.
I think that, as suggested in other answers, it is preferable to skip the unit tests execution while building your image. You can achieve this in several ways, for example (clean
is not necessary, but I usually clean before packaging the application):
# Compile and package the application to an executable JAR
RUN mvn clean package -skipTests
Or:
# Compile and package the application to an executable JAR
RUN mvn clean package -Dmaven.test.skip=true
The same approach is addressed in this SO related question, for instance.
Following this approach, if you really need to run your tests, it is preferable to use a devoted step in a CI/CD system pipeline, for example, instead of running it in the docker build.
Finally, please, consider why you are accessing a database in a unit test: in my opinion, and please, forgive me, because SO answer shouldn't be opinion based, it is something that you can find in an integration test, for example, but I think it is not commonly used in unit tests.
Even in the case that using a database is a must, for simplicity, predictability, in order to improve portability and build isolation, please, consider use an in-memory one like H2 with the necessary information, and run your tests against it instead.