【发布时间】:2019-08-14 00:11:33
【问题描述】:
我编写了一个简单的 java 程序,它应该连接到运行 MYSQL 服务器的主机并插入一条记录。 java 程序在带有 ubuntu 基础映像的 docker 容器中运行。此时我的 jar 工作正常,但还无法连接到主机 MYSQL 服务器。
我尝试了不同的 mysql 服务器安装并从其他 dockerfile 中复制,希望能够一起复制/粘贴一些有效的东西,但它变得混乱,我不知道哪些部分是必要的了。
Java 代码:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
class ConnectionTest {
private Connection conn;
ConnectionTest() throws IOException, ClassNotFoundException {
try {
test();
} catch (SQLException e) {
logError(e);
}
}
private void logError(SQLException e) throws IOException {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
String sStackTrace = sw.toString();
File fout = new File("logs.txt");
FileOutputStream fos = new FileOutputStream(fout);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
bw.write(sStackTrace);
bw.close();
}
private void test() throws SQLException, ClassNotFoundException { ;
String hostname = "localhost";
String dbName = "test";
String userName = "root";
String password = "";
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://" + hostname + ":3306/" + dbName + "?useLegacyDatetimeCode=false&serverTimezone=Europe/Paris", userName, password);
PreparedStatement prep = conn.prepareStatement("INSERT INTO test(Login, Password) values('test', 'test')");
prep.execute();
}
}
Dockerfile:
RUN mkdir -p /root/java
COPY jdk-8u221-linux-x64.tar.gz /
RUN tar -zxf jdk-8u221-linux-x64.tar.gz -C /root/java
RUN apt-get update
RUN update-alternatives --install /usr/bin/java java /root/java/jdk1.8.0_221/bin/java 100
ENV JAVA_HOME /root/java/jdk1.8.0_221/bin
RUN export JAVA_HOME
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server \
&& sed -i "s/127.0.0.1/0.0.0.0/g" /etc/mysql/mysql.conf.d/mysqld.cnf \
&& mkdir /var/run/mysqld \
&& chown -R mysql:mysql /var/run/mysqld
VOLUME ["/var/lib/mysql"]
CMD ["mysqld_safe"]
EXPOSE 3306
COPY lib /root/test/lib
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
入口点.sh:
chmod -R 777 /root/test
cd /root/test
java -cp "lib/*" -jar lib/DockerTest.jar
tail -f /dev/null
/root/test/lib 包含 mysql-connector-java.jar 和 DockerTest.jar。如果我在 jar 之前运行 mysqld,则服务器启动但 jar 不会启动。
服务器运行时的MYSQL状态:
$ winpty docker exec -it mysql_container service mysql status
* /usr/bin/mysqladmin Ver 8.42 Distrib 5.7.27, for Linux on x86_64
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Server version 5.7.27-0ubuntu0.16.04.1
Protocol version 10
Connection Localhost via UNIX socket
UNIX socket /var/run/mysqld/mysqld.sock
Uptime: 3 sec
Threads: 1 Questions: 4 Slow queries: 0 Opens: 105 Flush tables: 1 Open tables: 98 Queries per second avg: 1.333
仅运行 jar 时出错:
com.mysql.cj.jdbc.exceptions.CommunicationsException: 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 com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:832)
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:456)
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:240)
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:207)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:247)
at ConnectionTest.test(ConnectionTest.java:42)
at ConnectionTest.<init>(ConnectionTest.java:13)
at Main.main(Main.java:5)
Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure
【问题讨论】:
-
你能在终端上
telnet localhost 3306吗?您确定 MySQL 正在接受连接吗?您还做了哪些故障排除工作?我们真的无能为力,因为我们无权访问您的系统,而且 StackOverflow 未设置为调试/故障排除手持服务。 -
mysql 服务器正在接受连接,jar 在主机本地运行正常。我知道 jar 可以工作,并且我知道 mysql 服务器可以在 docker 容器上工作,我只是无法从 docker -> 主机数据库创建连接。还有哪些有用的信息?
-
对于初学者来说,两个系统上的网络配置的详细描述。显然,在一台 VM 主机上运行所有内容时,它可以工作,但在分离应用程序和数据库时,它就不行了。这意味着两个系统之间存在网络问题,所以从那里开始寻找。
-
通常建议是每个容器一个进程,请参阅devops.stackexchange.com/questions/447/…。您需要 Docker Compose 来轻松连接多个容器。
-
我的主机正在运行 xampp mysql 服务器,默认设置为 127.0.0.1:3306,防火墙配置为允许端口 3306 上的所有传入连接。我的 docker 容器没有任何连接设置,我想如果容器中的某些东西向 3306 发送某些东西,并且它被映射到主机本地 3306 端口,它会直接通过,但它不会。