【问题标题】:How to: Docker container running java jar connecting to host mysql server?如何:运行 java jar 的 Docker 容器连接到主机 mysql 服务器?
【发布时间】: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 端口,它会直接通过,但它不会。

标签: java mysql docker ubuntu


【解决方案1】:

如果您使用的是 Spring Framework,如果 MySQL 在您的本地/主机上运行,​​您可以将 application.properties 中的 spring.datasource.url 设置为使用 host.docker.internal:3306

spring.datasource.url=jdbc:mysql://host.docker.internal:3306/<yourdatabase>

【讨论】:

    猜你喜欢
    • 2023-03-23
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    • 2016-01-05
    • 2021-07-02
    • 2019-07-20
    • 2015-04-07
    • 2020-09-28
    相关资源
    最近更新 更多