Docker部署的Java项目与MySQL容器连接失败排查求助
容器间MySQL连接失败问题分析
问题背景
所有部署在Linux虚拟机上:MySQL容器将3306端口映射至主机3307,Java项目容器将8080端口映射至主机8080,两者均可正常运行。但Java项目使用jdbc:mysql://mysql:3307/fakenews?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai连接MySQL时失败,换成虚拟机IP:3307则可正常连接。两个容器处于同一flora网桥,Java项目容器能够ping通mysql容器。
错误日志
10:07:27:498 ERROR 1 --- [reate-375097969] com.alibaba.druid.pool.DruidDataSource : create connection SQLException, url: jdbc:mysql://mysql:3307/fakenews?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai, errorCode 0, state 08001 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:110) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:73) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:898) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:823) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:448) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:241) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:198) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1657) ~[druid-1.2.6.jar!/:1.2.6] at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1723) ~[druid-1.2.6.jar!/:1.2.6] at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2801) ~[druid-1.2.6.jar!/:1.2.6] 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 jdk.internal.reflect.GeneratedConstructorAccessor33.newInstance(Unknown Source) ~[na:na] at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na] at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) ~[na:na] at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:151) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:167) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:89) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.NativeSession.connect(NativeSession.java:120) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:842) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] ... 7 common frames omitted Caused by: java.net.UnknownHostException: mysql at java.base/java.net.InetAddress$CachedAddresses.get(InetAddress.java:797) ~[na:na] at java.base/java.net.InetAddress.getAllByName0(InetAddress.java:1509) ~[na:na] at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1368) ~[na:na] at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1302) ~[na:na] at com.mysql.cj.protocol.StandardSocketFactory.connect(StandardSocketFactory.java:130) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:63) ~[mysql-connector-java-8.0.30.jar!/:8.0.30] ... 9 common frames omitted
相关配置与运行信息
Java项目Dockerfile
FROM openjdk:11.0 ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone COPY TextAnalyse.jar /app.jar ENTRYPOINT ["java", "-jar", "/app.jar"]
容器运行状态(docker ps输出)
CONTAINER ID IMAGE PORTS STATUS NAMES 5bcdd5eff02f textanalyse 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp Up 24 minutes ta 3f44be91fb18 mysql 33060/tcp, 0.0.0.0:3307->3306/tcp, :::3307->3306/tcp Up About an hour mysql 584173fb038f nginx 0.0.0.0:80->80/tcp, :::80->80/tcp Up 44 minutes nginx
容器连通性测试
root@1fce4b851205:/# ping mysql PING mysql (172.18.0.2) 56(84) bytes of data. 64 bytes from mysql.flora (172.18.0.2): icmp_seq=1 ttl=64 time=3.09 ms 64 bytes from mysql.flora (172.18.0.2): icmp_seq=2 ttl=64 time=0.069 ms 64 bytes from mysql.flora (172.18.0.2): icmp_seq=3 ttl=64 time=0.106 ms 64 bytes from mysql.flora (172.18.0.2): icmp_seq=4 ttl=64 time=1.34 ms 64 bytes from mysql.flora (172.18.0.2): icmp_seq=5 ttl=64 time=0.093 ms 64 bytes from mysql.flora (172.18.0.2): icmp_seq=6 ttl=64 time=0.168 ms 64 bytes from mysql.flora (172.18.0.2): icmp_seq=7 ttl=64 time=0.072 ms
问题原因分析
- 端口使用错误:容器间同一网桥内通信时,应访问MySQL容器内部的3306端口,而非主机映射的3307端口。主机端口映射是为外部(虚拟机主机或其他外部网络)访问容器服务设计的,容器间直接通信走容器自身的服务端口即可。
- 异常误导性:错误日志中出现
UnknownHostException: mysql,但实际ping测试证明mysql主机名可以正常解析,该异常是连接端口失败后触发的连带错误,核心问题是尝试访问mysql容器未开放的3307端口导致连接失败。
解决办法
修改JDBC连接URL为:
jdbc:mysql://mysql:3306/fakenews?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
确保MySQL容器内部的3306端口正常监听(MySQL默认启用该端口)。
内容的提问来源于stack exchange,提问作者Flora
相关产品推荐
相关产品推荐

