Docker部署Tomcat应用连接MySQL报CannotGetJdbcConnectionException
问题分析
从错误栈核心的java.net.ConnectException: Connection refused可以判断:Tomcat容器无法连接到MySQL服务,根源是Docker容器网络的访问逻辑误解——在容器内部,127.0.0.1指向容器自身,而非宿主机的MySQL容器;而Docker Compose默认会创建独立桥接网络,服务之间必须通过服务名称互相访问,不能用localhost。
解决方案
1. 修改Spring数据库连接配置
更新servlet-context.xml中的数据源配置,适配Docker网络和MySQL驱动版本:
<beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <!-- 替换为MySQL Connector/J 8.x的官方驱动类(旧驱动已废弃) --> <beans:property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <!-- 用docker-compose服务名`mysql`替代127.0.0.1,适配容器网络 --> <beans:property name="url" value="jdbc:mysql://mysql:3306/SomeDB?serverTimezone=UTC&allowPublicKeyRetrieval=true"/> <beans:property name="username" value="root" /> <beans:property name="password" value="root"/> </beans:bean>
说明:
allowPublicKeyRetrieval=true是MySQL 8.x版本的必填参数,避免公钥检索失败的报错。- 服务名
mysql对应docker-compose.yml中定义的MySQL服务名称,Docker会自动解析为对应容器的IP。
2. 优化容器启动顺序(可选但推荐)
在docker-compose.yml的web服务中添加depends_on,确保MySQL先于Tomcat启动:
version: "3.9" services: mysql: # 原有配置保持不变 container_name: mysql image: mysql ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: SomeDB volumes: - ./data:/var/lib/mysql - ./src/main/db:/docker-entrypoint-initdb.d/:ro web: container_name: tomcat build: . ports: - "8080:8080" # 添加依赖,保证MySQL先启动 depends_on: - mysql
注意:depends_on仅保证启动顺序,不确保MySQL完全就绪。若需等待MySQL服务可用,可添加健康检查或使用wait-for-it等工具。
3. 验证MySQL用户权限(若仍无法连接)
进入MySQL容器终端,执行以下SQL,开放root用户的跨IP访问权限:
ALTER USER 'root'@'%' IDENTIFIED BY 'root'; FLUSH PRIVILEGES;
默认情况下,MySQL的root用户仅允许localhost访问,而Tomcat容器处于独立网络节点,必须开放权限才能连接。
验证步骤
- 重新构建并启动容器:
docker-compose down && docker-compose up --build
- 进入Tomcat容器测试网络连通性:
docker exec -it tomcat ping mysql
若能正常ping通,说明网络配置生效。
内容的提问来源于stack exchange,提问作者NNikN
相关产品推荐
相关产品推荐

