Spring Boot容器无法通过Docker容器名连接MariaDB的问题
问题描述
我有一个连接MariaDB数据库的Spring Boot应用,尝试用docker-compose部署时出现以下错误:
java.sql.SQLNonTransientConnectionException: Socket fail to connect to host:address=(host=maria_db)(port=10000) (type=primary). maria_db ... Caused by: java.net.UnknownHostException: maria_db
相关配置文件如下:
docker-compose.yml
version: "3.7" services: api_service: build: . restart: always ports: - "8080:8080" depends_on: - maria_db maria_db: image: "mariadb:10.5.8" restart: always ports: - "10000:3306" environment: MYSQL_DATABASE: app_db MYSQL_USER: exampleuser MYSQL_PASSWORD: examplepass MYSQL_ROOT_PASSWORD: examplepass
Spring应用Dockerfile
FROM openjdk:17-oracle COPY target/app-0.0.1.jar app-0.0.1.jar RUN ["java","-jar","/app-0.0.1.jar"]
application.properties
spring.datasource.url=jdbc:mariadb://maria_db:10000/app_db spring.datasource.username=exampleuser spring.datasource.password=examplepass spring.datasource.driver-class-name=org.mariadb.jdbc.Driver spring.jpa.hibernate.ddl-auto=update springdoc.api-docs.path = /javainuse-openapi
使用版本信息:
- Spring Boot 3.0.2
- Java 17
- Docker Engine v20.10.22(Docker Windows)
作为Docker新手,按资料配置仍报错,请问哪里操作有误?
错误分析与修复方案
你的问题集中在三个关键配置错误上:
1. Dockerfile启动指令错误
Dockerfile中使用RUN指令启动jar包,这会在镜像构建阶段执行启动命令——此时容器网络尚未创建,根本无法解析maria_db这个主机名,必然报错。
修复:将RUN替换为CMD(容器启动时执行的命令):
FROM openjdk:17-oracle COPY target/app-0.0.1.jar app-0.0.1.jar CMD ["java","-jar","/app-0.0.1.jar"]
2. 数据库连接端口错误
Docker Compose同一网络内的服务通信,直接使用容器内部端口即可,无需用宿主机映射的端口。MariaDB容器内部默认端口是3306,你映射了宿主机10000端口到容器3306,但Spring应用连接时应该用容器内部的3306,而非10000。
修复:修改application.properties中的数据库URL:
spring.datasource.url=jdbc:mariadb://maria_db:3306/app_db
3. depends_on的局限性
depends_on仅保证容器的启动顺序,不保证数据库服务完全初始化就绪。Spring应用启动时,可能数据库还没完成初始化,导致连接失败。
修复方案(二选一):
- 给Spring应用添加连接重试机制,在application.properties中追加:
spring.datasource.hikari.connection-timeout=60000 spring.datasource.hikari.maximum-pool-size=5 spring.datasource.hikari.validation-timeout=3000 spring.jpa.properties.hibernate.connection.provider_disables_autocommit=true - 在docker-compose中添加健康检查,让API服务等待数据库就绪后再启动:
api_service: build: . restart: always ports: - "8080:8080" depends_on: maria_db: condition: service_healthy maria_db: image: "mariadb:10.5.8" restart: always ports: - "10000:3306" environment: MYSQL_DATABASE: app_db MYSQL_USER: exampleuser MYSQL_PASSWORD: examplepass MYSQL_ROOT_PASSWORD: examplepass healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-pexamplepass"] interval: 5s timeout: 5s retries: 10
内容的提问来源于stack exchange,提问作者MilanJ
相关产品推荐
相关产品推荐

