简体   繁体   中英

Spring cannot connect to postgres when using docker

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    

You're trying to run mvn spring-boot:run from a Dockerfile RUN 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 using javac to compile a source file and java 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 same docker-compose.yml file.

Split the Dockerfile into two separate lines to build the application, and then to run it as the main container command:

FROM maven:3.6.0-jdk-11
WORKDIR /app
COPY . .      # (don't repeat /app directory name)

# At build time, only compile the application but do not run it
RUN mvn clean install

# When you launch the container, this will be the main command
CMD mvn spring-boot:run

@david-maze 's solution was almost good for my case. However, I solved the problem with this following Dockerfile:

FROM maven:3.6.0-jdk-11
WORKDIR /app
COPY . .

# At build time, only compile the application but do not run it
RUN mvn clean package -DskipTests -q

# When you launch the container, this will be the main command
CMD mvn spring-boot:run

also had to add an alias for the database container:

postgres:
    image: postgres
    container_name: db
    expose:
      - "5432"
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: nanobox
      networks:
        some-net:
          aliases:
            - auth-module.dev

Maven was running tests that resulted in container launch failure because there was no database.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM