I am trying to containerise a Spring Boot project that uses another containerised Postgres database, but it seems the Spring project cannot connect to the database because it cannot resolve the hostname.
Dockerfile:
FROM maven:3.6.0-jdk-11
WORKDIR /app
COPY . /app
RUN mvn clean install spring-boot:run -q
Docker compose:
version: "3.7"
services:
postgres:
image: postgres
container_name: db
expose:
- "5432"
ports:
- "5432:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: nanobox
networks:
- app-network
backend:
restart: always
build:
context: nanobox
volumes:
- ./nanobox:/app
environment:
- SECRET=bigsecret
ports:
- 8081:8081
networks:
- app-network
depends_on:
- postgres
networks:
app-network:
driver: bridge
application.properties:
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
#debug=false
spring.datasource.platform=postgres
spring.datasource.url=jdbc:postgresql://postgres:5432/nanobox
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.jpa.generate-ddl=true
spring.jpa.database=postgresql
spring.jpa.hibernate.ddl-auto=update
#spring.jpa.properties.hibernate.jdbc.lob.not_contextual_creation=true
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
debug=true
spring.mvc.log-request-details=true
auth.secret={SECRET}
storage.prefix = /tmp/uploads/
docker compose up fails with the following exceptions:
#8 44.67 Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution
[..]
#8 44.67 Caused by: org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution
[..]
#8 44.68 Caused by: org.postgresql.util.PSQLException: The connection attempt failed.
[..]
#8 44.68 Caused by: java.net.UnknownHostException: postgres
It seems that for some reason docker compose refuses to start the postgres container before the Spring application, even the command:
docker compose up postgres backend
results in:
[+] Building 8.3s (8/8) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 31B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/maven:3.6.0-jdk-11 1.5s
=> [1/4] FROM docker.io/library/maven:3.6.0-jdk-11@sha256:6a0430ded2cfaba7e16080f4cc097c9c65d1406b3b235d0fcfcfd84c354c4177 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 18.55kB 0.0s
=> CACHED [2/4] WORKDIR /app 0.0s
=> CACHED [3/4] COPY . /app
2
Answers
@david-maze 's solution was almost good for my case. However, I solved the problem with this following Dockerfile:
also had to add an alias for the database container:
Maven was running tests that resulted in container launch failure because there was no database.
You’re trying to run
mvn spring-boot:run
from a DockerfileRUN
instruction; that happens while you’re trying to build the image, not when you go to run the container later. (It’s similar to the difference between usingjavac
to compile a source file andjava
to run the built class file.) For reasons beyond the scope of this answer, the build phase can’t connect to other containers, even if they’re declared in the samedocker-compose.yml
file.Split the Dockerfile into two separate lines to build the application, and then to run it as the main container command: