DockerHub:无法打开用于DDL执行的JDBC连接(无法创建到数据库服务器的连接)
我正在学习Spring Boot,并在做一个需要连接到一个Spring Boot API的应用。我的API在本地运行时没有问题,但在使用Docker时,找不到数据库。
编辑:我已经让镜像在Docker上运行起来。我不知道为什么第一次测试时它不起作用,但现在重启电脑后就能正常运行。然而,当我通过Github Actions将镜像推送到DockerHub,并用Docker Desktop拉取时,仍然无法连接到数据库,错误相同。
这是我的maven-publish.yml
name: Build and Push Docker Image
on:
push:
branches:
- main
jobs:
test:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
- name: Running Unit Tests
run:
mvn -f pom.xml clean test
build:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name: Build with Maven
run: mvn -f pom.xml clean package
- name: Set up Docker Buildx
uses: docker/[email protected]
- name: Login to Docker Hub
uses: docker/[email protected]
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/[email protected]
with:
context: .
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/api-project-pmt:latest
这是我的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.13</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.iscod</groupId>
<artifactId>api-project-pmt</artifactId>
<version>1.0.0</version>
<name>api-project-pmt</name>
<description>The backend API of project PMT</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>21</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<!-- Exclude Hibernate core -->
<exclusion>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.5.2.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>3.5.12</version>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.6.3</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
-javaagent:${settings.localRepository}/org/mockito/mockito-core/${mockito.version}/mockito-core-${mockito.version}.jar
-Xshare:off
</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.14</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
我的.env文件
# =========================
# MySQL
# =========================
MYSQL_ROOT_USER=root
MYSQL_ROOT_PASSWORD=3de7Qt?bMtHXGJpo
MYSQL_DATABASE=pmt
MYSQL_USER=user
MYSQL_PASSWORD=password
SERVER_PORT=8081
# =========================
# Spring Boot / JDBC
# =========================
MYSQL_HOST=mysql-db
MYSQL_PORT=3306
MYSQL_JDBC_PARAMS=createDatabaseIfNotExist=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true&autoReconnect=true
# =========================
# Mail
# =========================
[email protected]
MAIL_PASSWORD=password
我的application.properties
spring.application.name=api-project-pmt
server.port=8081
spring.datasource.url=jdbc:mysql://mysql-db:3306/pmt?createDatabaseIfNotExist=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true&autoReconnect=true
spring.datasource.username=root
spring.datasource.password=3de7Qt?bMtHXGJpo
spring.datasource.hikari.initializationFailTimeout=60000
spring.datasource.hikari.connectionTimeout=30000
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.defer-datasource-initialization=true
spring.sql.init.mode=always
spring.mail.host=smtp.gmail.com
spring.mail.port=587
[email protected]
spring.mail.password=password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
logging.level.org.springframework=DEBUG
logging.level.org.springframework.boot.context=DEBUG
我的docker-compose.yaml
services:
mysql-db:
container_name: mysql-db
image: mysql:8.4.7
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- db:/var/lib/mysql
ports:
- "3305:3306"
networks:
- spring-cloud-network
restart: unless-stopped
project-server:
container_name: tmp-server
build: .
ports:
- "8081:8081"
environment:
- spring.datasource.url=jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DATABASE}?${MYSQL_JDBC_PARAMS}
- spring.datasource.username=${MYSQL_USER}
- spring.datasource.password=${MYSQL_PASSWORD}
networks:
- spring-cloud-network
restart: on-failure:10
networks:
spring-cloud-network:
driver: bridge
volumes:
db:
以及我的Dockerfile
# Use a base image with OpenJDK Java 17 installed
FROM eclipse-temurin:21
# Set the working directory in the container
WORKDIR /app
# Copy the packaged Spring Boot application JAR file into the container
COPY target/api-project-pmt-1.0.0.jar /app/api-project-pmt-1.0.0.jar
# Expose port 8081
EXPOSE 8081
# Specify the command to run the Spring Boot application when the container starts
CMD ["java", "-jar", "api-project-pmt-1.0.0.jar"]
我已经尝试了多种解决方案:
- 将
org.hibernate.core从spring-starter-data-jpa中排除 - 将
healthcheck改为restart: on-failure:10 - 在属性中添加连接超时设置
spring.datasource.hikari.initializationFailTimeout=60000
spring.datasource.hikari.connectionTimeout=30000
但我一直遇到这个错误
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:388) ~[spring-orm-6.2.17.jar!/:6.2.17]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:419) ~[spring-orm-6.2.17.jar!/:6.2.17]
... 24 common frames omitted
Caused by: java.sql.SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:102) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:81) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:55) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:65) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:914) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:833) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:416) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:237) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:180) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:144) ~[HikariCP-6.3.3.jar!/:na]
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:370) ~[HikariCP-6.3.3.jar!/:na]
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:207) ~[HikariCP-6.3.3.jar!/:na]
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:488) ~[HikariCP-6.3.3.jar!/:na]
at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:576) ~[HikariCP-6.3.3.jar!/:na]
at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:97) ~[HikariCP-6.3.3.jar!/:na]
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111) ~[HikariCP-6.3.3.jar!/:na]
at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final]
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:437) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:46) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final]
... 47 common frames omitted
Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62) ~[na:na]
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502) ~[na:na]
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486) ~[na:na]
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:52) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:95) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:140) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:156) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:79) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.NativeSession.connect(NativeSession.java:142) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:854) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
... 61 common frames omitted
Caused by: java.net.UnknownHostException: mysql-db
at java.base/java.net.InetAddress$CachedLookup.get(InetAddress.java:988) ~[na:na]
at java.base/java.net.InetAddress.getAllByName0(InetAddress.java:1818) ~[na:na]
at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1688) ~[na:na]
at com.mysql.cj.protocol.StandardSocketFactory.connect(StandardSocketFactory.java:121) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:53) ~[mysql-connector-j-9.6.0.jar!/:9.6.0]
... 63 common frames omitted
解决方案
所以我不太明白如何正确使用DockerHub。当从DockerHub拉取镜像时,它不包含下载和启动MySQL服务的指令,这意味着我需要创建一个桥接网络并手动启动这两个服务。我通过在两个不同的终端执行这三条命令来解决。第一条命令创建桥接,第二条启动MySQL,第三条启动Spring Boot应用
docker network create spring-cloud-network
docker run -it --rm --name mysql-db --network spring-cloud-network `
-e MYSQL_ROOT_PASSWORD=3de7Qt?bMtHXGJpo `
-e MYSQL_DATABASE=pmt `
-e MYSQL_USER=user `
-e MYSQL_PASSWORD=password `
-v mysql-db:/var/lib/mysql `
-p 3305:3306 `
mysql:8.4.7
docker container run -it --rm --name api-project-pmt-hub --network spring-cloud-network `
-e MYSQL_DATABASE=pmt `
-e MYSQL_USER=user `
-e MYSQL_PASSWORD=password `
-p 8081:8081 `
gwendal25/api-project-pmt:latest
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。