当通过 Dockerfile 上的 gradle 图像触发时,Jooq 无法找到数据库
Jooq unable to find database when triggered via a gradle image on Dockerfile
我有一个 Dockerfile,它使用 gradle 构建我的 Spring 引导应用程序,然后将其复制到容器中并触发它。这是它的样子:
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"]
很简单,它会执行Gradle,然后将jar 添加到docker 容器中。到目前为止,一切都很好。提供数据库后,将在 docker-compose.yml 中使用此 Dockerfile(应用程序需要数据库才能运行)。这就是 docker-compose.yml 的样子:
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:
如您所见,应用程序映像是最后构建的,一旦数据库映像准备就绪,也是在 flyway 执行迁移之后。我在构建应用程序期间遇到的问题。
所以一旦 gradle 启动,它就会做所有它必须做的事情。但在某一时刻,它需要 Jooq,根据数据库中现有的表自动生成一些 类。在这里出了点问题。构建爆炸并告诉我:
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
它说无法连接到数据库。这是为什么?这是我的 build.gradle 文件
中的 Jooq 配置
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())
}
}
}
我很困惑,我不确定我明白发生了什么。如果我要使用 docker-compose 来单独启动数据库映像,然后我从我的终端手动 运行 gradle(不是 [=41 中的 gradle =]), 那些 类 将毫无问题地生成。所以我不知道什么时候从 Dockerfile 使用 gradle Jooq 找不到数据库。任何的想法?
我是否还需要以某种方式从 Dockerfile 中触发 Jooq,就像我触发 gradle 一样?有人可以帮我解决这个问题吗,我有点卡住了。
更新
我尝试将 jooq 配置中的 url 更改为使用 yurldb 而不是 localhost,因为可能在容器内联网时 url 重新定位到容器的名称,但那没有不工作。这是怎么回事:
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
问题是您在 build.gradle
.
中的 jooq
插件配置中将 localhost
作为数据库主机
您已在其他地方为 DB_HOST
正确设置了环境变量,因此我假设您了解服务名称是 DNS 名称,当其他服务连接到公共网络时,您可以使用该名称来引用其他服务网络。你应该改变
url = 'jdbc:postgresql://localhost:5432/yurldb'
到
url = 'jdbc:postgresql://yurldb:5432/yurldb'
或者你可以在应用服务的环境变量中获取db的host,然后从build.gradle
中读取它:
def db = System.getenv('DB_HOST')
url = "jdbc:postgresql://${db}:5432/yurldb"
我有一个 Dockerfile,它使用 gradle 构建我的 Spring 引导应用程序,然后将其复制到容器中并触发它。这是它的样子:
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"]
很简单,它会执行Gradle,然后将jar 添加到docker 容器中。到目前为止,一切都很好。提供数据库后,将在 docker-compose.yml 中使用此 Dockerfile(应用程序需要数据库才能运行)。这就是 docker-compose.yml 的样子:
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:
如您所见,应用程序映像是最后构建的,一旦数据库映像准备就绪,也是在 flyway 执行迁移之后。我在构建应用程序期间遇到的问题。 所以一旦 gradle 启动,它就会做所有它必须做的事情。但在某一时刻,它需要 Jooq,根据数据库中现有的表自动生成一些 类。在这里出了点问题。构建爆炸并告诉我:
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
它说无法连接到数据库。这是为什么?这是我的 build.gradle 文件
中的 Jooq 配置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())
}
}
}
我很困惑,我不确定我明白发生了什么。如果我要使用 docker-compose 来单独启动数据库映像,然后我从我的终端手动 运行 gradle(不是 [=41 中的 gradle =]), 那些 类 将毫无问题地生成。所以我不知道什么时候从 Dockerfile 使用 gradle Jooq 找不到数据库。任何的想法? 我是否还需要以某种方式从 Dockerfile 中触发 Jooq,就像我触发 gradle 一样?有人可以帮我解决这个问题吗,我有点卡住了。
更新 我尝试将 jooq 配置中的 url 更改为使用 yurldb 而不是 localhost,因为可能在容器内联网时 url 重新定位到容器的名称,但那没有不工作。这是怎么回事:
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
问题是您在 build.gradle
.
jooq
插件配置中将 localhost
作为数据库主机
您已在其他地方为 DB_HOST
正确设置了环境变量,因此我假设您了解服务名称是 DNS 名称,当其他服务连接到公共网络时,您可以使用该名称来引用其他服务网络。你应该改变
url = 'jdbc:postgresql://localhost:5432/yurldb'
到
url = 'jdbc:postgresql://yurldb:5432/yurldb'
或者你可以在应用服务的环境变量中获取db的host,然后从build.gradle
中读取它:
def db = System.getenv('DB_HOST')
url = "jdbc:postgresql://${db}:5432/yurldb"