DockerHub:无法打开用于DDL执行的JDBC连接(无法创建到数据库服务器的连接)

后端开发 2026-07-11

我正在学习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"]

我已经尝试了多种解决方案:

  1. org.hibernate.corespring-starter-data-jpa 中排除
  2. healthcheck 改为 restart: on-failure:10
  3. 在属性中添加连接超时设置
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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章