问题
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