Jooq unable to find database when triggered via a gradle image on Dockerfile

╄→尐↘猪︶ㄣ 提交于 2020-06-02 05:49:19

问题


I have a Dockerfile that uses gradle to build my Spring boot application just before coping it into the container and trigger it. This is how it looks:

FROM gradle:5.4.1-jdk8-alpine AS build
COPY --chown=gradle:gradle . /home/gradle/src
WORKDIR /home/gradle/src
RUN gradle build --no-daemon

FROM openjdk:8-jdk-alpine
EXPOSE 8080
RUN mkdir /app
COPY --from=build /home/gradle/src/build/libs/*.jar yurlapp.jar
ENTRYPOINT ["java","-jar" , "/yurlapp.jar"]

It's quite simple, it will execute Gradle and the jar will be added into the docker container. So far so good. This Dockerfile will be used inside a docker-compose.yml once the database is provided(the DB is required for the app to work). This is how that docker-compose.yml looks like:

version: '2.1'
services:
  yurldb:
    image: postgres:11
    container_name: yurldb
    networks:
      - yunet
    ports:
      - 5432:5432
    environment:
      - POSTGRES_DB=yurldb
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=somepassword
    volumes:
      - ./init.sql:/docker-entrypoint-initdb.d/
      - yudata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 10s
      retries: 5
  flyway:
    image: boxfuse/flyway
    command: -url=jdbc:postgresql://yurldb:5432/yurldb -schemas=public -user=postgres -password=somepassword migrate
    networks:
      - yunet
    volumes:
      - .:/flyway/sql
    depends_on:
      yurldb:
        condition: service_healthy
  yurlapp:
    container_name: yurlapp
    image: javing/yurlapp:0.0.1
    build:
      context: .
      dockerfile: Dockerfile
    networks:
      - yunet
    ports:
      - 8080:8080
    environment:
      - DB_HOST=yurldb #the name of the DB container is used as url
    depends_on:
      yurldb:
        condition: service_healthy
      flyway:
        condition: service_healthy
networks:
  yunet:
volumes:
  yudata:

As you can see the app image be built last, once the database image is ready and also after flyway performs the migrations. The problem that I have happens during the building of the app. So once gradle starts it will do all it has to do. But at one point it requires Jooq, to autogenerate some classes based on the existing tables on the database. And in here something goes wrong. The build blows up and tells me this:

Task :generateSampleJooqSchemaSource FAILED

FAILURE: Build failed with an exception.

* Where:
Build file '/home/gradle/src/build.gradle' line: 81

* What went wrong:
Execution failed for task ':generateSampleJooqSchemaSource'.
> jOOQ source code generation failed:

  Jun 01, 2020 7:37:39 PM org.jooq.tools.JooqLogger info
  INFO: Initialising properties  : /home/gradle/src/build/tmp/generateSampleJooqSchemaSource/config.xml
  Jun 01, 2020 7:37:39 PM org.jooq.tools.JooqLogger error
  SEVERE: Cannot read /home/gradle/src/build/tmp/generateSampleJooqSchemaSource/config.xml. Error : Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
  org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:285)
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
    at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:211)
    at org.postgresql.Driver.makeConnection(Driver.java:459)
    at org.postgresql.Driver.connect(Driver.java:261)
    at org.jooq.codegen.GenerationTool.run0(GenerationTool.java:342)
    at org.jooq.codegen.GenerationTool.run(GenerationTool.java:221)
    at org.jooq.codegen.GenerationTool.generate(GenerationTool.java:216)
    at org.jooq.codegen.GenerationTool.main(GenerationTool.java:188)
  Caused by: java.net.ConnectException: Connection refused (Connection refused)
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at org.postgresql.core.PGStream.<init>(PGStream.java:81)
    at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:93)
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:197)
    ... 8 more

It says that it can't connect to the database. Why is that? This is the Jooq configuration I have in my build.gradle file

jooq {
    sample(sourceSets.main) {
        jdbc {
            driver = 'org.postgresql.Driver'
            url = 'jdbc:postgresql://localhost:5432/yurldb'
            user = 'postgres'
            password = 'somepassword'
        }
        generator {
            database() {
                name = 'org.jooq.meta.postgres.PostgresDatabase'
                inputSchema = 'public'
                includes = '.*'
            }
            target {
                packageName = 'com.javing.yurl'
                directory = 'build/generated/java'
            }
        }
    }
}

tasks.generateSampleJooqSchemaSource.with {
    def out = new ByteArrayOutputStream()
    javaExecSpec = { JavaExecSpec s ->
        s.standardOutput = out
        s.errorOutput = out
        s.ignoreExitValue = true
        s.jvmArgs '-Xmx512M'
    }
    execResultHandler = { ExecResult r ->
        if (r.exitValue != 0) {
            throw new RuntimeException('jOOQ source code generation failed:\n\n' + out.toString())
        }
    }
}

I am very confused, I am not sure I understand what is happening. If I was to use docker-compose to just boot the database image just by itself and then I run gradle manually from my terminal(not the gradle from docker), those classes will be generated without problem. So I don't know when the gradle is used from the Dockerfile Jooq fails to find the DB. Any idea? Do i also need to trigger Jooq maybe from the Dockerfile somehow, in the same way that I triggered gradle? Can someone help me with this please, I am a bit stuck.

Update I tried changing the url in the jooq config to use yurldb instead of localhost since maybe when networking inside the container the url resloves to the name of the container, but that didn't work. What happens is this:

FAILURE: Build failed with an exception.

* Where:
Build file '/home/gradle/src/build.gradle' line: 81

* What went wrong:
Execution failed for task ':generateSampleJooqSchemaSource'.
> jOOQ source code generation failed:

  Jun 01, 2020 8:29:57 PM org.jooq.tools.JooqLogger info
  INFO: Initialising properties  : /home/gradle/src/build/tmp/generateSampleJooqSchemaSource/config.xml
  Jun 01, 2020 8:30:08 PM org.jooq.tools.JooqLogger error
  SEVERE: Cannot read /home/gradle/src/build/tmp/generateSampleJooqSchemaSource/config.xml. Error : The connection attempt failed.
  org.postgresql.util.PSQLException: The connection attempt failed.
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:297)
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
    at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:211)
    at org.postgresql.Driver.makeConnection(Driver.java:459)
    at org.postgresql.Driver.connect(Driver.java:261)
    at org.jooq.codegen.GenerationTool.run0(GenerationTool.java:342)
    at org.jooq.codegen.GenerationTool.run(GenerationTool.java:221)
    at org.jooq.codegen.GenerationTool.generate(GenerationTool.java:216)
    at org.jooq.codegen.GenerationTool.main(GenerationTool.java:188)
  Caused by: java.net.SocketTimeoutException: connect timed out
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at org.postgresql.core.PGStream.<init>(PGStream.java:81)
    at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:93)
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:197)
    ... 8 more

回答1:


The problem is that you have localhost as the database host in the configuration of your jooq plugin in build.gradle.

You have correctly set environment variables for DB_HOST in other places so I assume you understand that name of the service is the DNS name that you can use to refer to other services when they are connected to a common network. You should change

url = 'jdbc:postgresql://localhost:5432/yurldb'

to

url = 'jdbc:postgresql://yurldb:5432/yurldb'

or you can get the host of db in environment variable for application service and then read it from build.gradle :

def db = System.getenv('DB_HOST')
url = "jdbc:postgresql://${db}:5432/yurldb"


来源:https://stackoverflow.com/questions/62140023/jooq-unable-to-find-database-when-triggered-via-a-gradle-image-on-dockerfile

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!