春季引导在 Docker 环境中无法与 MySQL 数据库通信

huangapple go评论78阅读模式
英文:

Spring Boot unable to communicate with MySQL DB in docker environment

问题

我正在尝试运行一个Spring Boot微服务Docker镜像。它从Config服务器获取数据库连接属性。然而,它无法连接到容器。

错误:

JdbcEnvironmentInitiator - HHH000342:无法获取连接以查询元数据:通信链接失败
最后一个成功发送到服务器的数据包距离现在0毫秒。驱动程序未收到服务器的任何数据包。

异常:

at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174) ~[mysql-connector-java-8.0.21.jar!/:8.0.21]
引起于:
at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.8.0_242]
2020-09-28 11:39:32.782 [:] 警告 [task-1] o.h.e.j.s.SqlExceptionHelper - SQL错误:0,SQL状态:08S01
 1 --- [         task-1] o.h.engine.jdbc.spi.SqlExceptionHelper   :SQL错误:0,SQL状态:08S01
2020-09-28 11:39:32.791 [:] 错误 [task-1] o.h.e.j.s.SqlExceptionHelper - 通信链接失败

最后一个成功发送到服务器的数据包距离现在0毫秒。驱动程序未收到服务器的任何数据包。
 1 --- [         task-1] o.h.engine.jdbc.spi.SqlExceptionHelper   :通信链接失败

最后一个成功发送到服务器的数据包距离现在0毫秒。驱动程序未收到服务器的任何数据包。

位于Config Server的属性:

shopping-service.datasource.url:jdbc:mysql://A.B.C.D:3306/shoppingCartDB
shopping-service.datasource.username:root
shopping-service.datasource.password:root

A.B.C.D 是我的Docker主机IP。

application.yaml

datasource:
    url: ${shopping-service.datasource.url}
    username: ${shopping-service.datasource.username}
    password: ${shopping-service.datasource.password}
    #driver-class-name: com.mysql.jdbc.Driver
  jpa:
    generate-ddl: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL8Dialect
        show_sql: true
        ddl-auto: create-drop
  profiles:
    active: dev

我从Docker Hub拉取了MySQL 8.0的Docker镜像。

docker pull mysql/mysql-server:8.0
docker run --name=mysql-container -d mysql/mysql-server:8.0

将密码更改为"root"。

mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'root';
查询成功,受影响的行数:0(0.02秒)

创建数据库:

mysql> create DATABASE shoppingCartDB;
查询成功,受影响的行数:1(0.00秒)

mysql> exit

Docker运行

docker run -p 5000:5000 shoppingms:latest --env shopping-service.configserverurl=http://A.B.C.D:8888 --env shopping-service.eureka.url=http://A.B.C.D:4444/eureka

它能够从配置服务器获取属性。我检查了日志。错误来自于此行:

com.zaxxer.hikari.HikariDataSource       :HikariPool-1 - Starting...

在我的本地环境中,我能够使用相同的连接参数使用本地安装的MySQL数据库。然而,在Docker中,我遇到了异常。请问有谁能帮我找出问题所在。

更新:

将MySQL容器暴露到端口3306后,错误现在如下:

2020-09-28 12:07:43.942 [:] 警告 [task-1] o.h.e.j.e.i.JdbcEnvironmentInitiator - HHH000342:无法获取连接以查询元数据:null,来自服务器的消息:"Host 'Some-IP' 不允许连接到此MySQL服务器"
     1 --- [         task-1] o.h.e.j.e.i.JdbcEnvironmentInitiator     :HHH000342:无法获取连接以查询元数据:null,来自服务器的消息:"Host 'Some-IP' 不允许连接到此MySQL服务器"

2020-09-28 12:07:49.219 [:] 警告 [task-1] o.h.e.j.s.SqlExceptionHelper - SQL错误:1130,SQL状态:HY000
 1 --- [         task-1] o.h.engine.jdbc.spi.SqlExceptionHelper   :SQL错误:1130,SQL状态:HY000
2020-09-28 12:07.49.225 [:] 错误 [task-1] o.h.e.j.s.SqlExceptionHelper - null,来自服务器的消息:"Host 'Some-IP' 不允许连接到此MySQL服务器"
 1 --- [         task-1] o.h.engine.jdbc.spi.SqlExceptionHelper   :null,来自服务器的消息:"Host 'Some-IP' 不允许连接到此MySQL服务器"
英文:

I am trying to run a springboot microservice docker image. It fetches the DB connection properties from a Config server. However it is unable to connect to the container.

Error :

JdbcEnvironmentInitiator - HHH000342: Could not obtain connection to query metadata : 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.

Exception :

at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174) ~[mysql-connector-java-8.0.21.jar!/:8.0.21]
Caused by :
at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.8.0_242]
2020-09-28 11:39:32.782 [ : ] WARN  [task-1] o.h.e.j.s.SqlExceptionHelper - SQL Error: 0, SQLState: 08S01
 1 --- [         task-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: 08S01
2020-09-28 11:39:32.791 [ : ] ERROR [task-1] o.h.e.j.s.SqlExceptionHelper - 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.
 1 --- [         task-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : 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.

Properties located at Config Server

shopping-service.datasource.url: jdbc:mysql://A.B.C.D:3306/shoppingCartDB
shopping-service.datasource.username: root
shopping-service.datasource.password: root

A.B.C.D is my docker host IP.

application.yaml

datasource:
    url: ${shopping-service.datasource.url}
    username: ${shopping-service.datasource.username}
    password: ${shopping-service.datasource.password}
    #driver-class-name: com.mysql.jdbc.Driver
  jpa:
    generate-ddl: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL8Dialect
        show_sql: true
        ddl-auto: create-drop
  profiles:
    active: dev

I have pulled the MySQL 8.0 docker image from docker hub.

docker pull mysql/mysql-server:8.0
docker run --name=mysql-container -d mysql/mysql-server:8.0

Changed the password to "root".

mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'root';
Query OK, 0 rows affected (0.02 sec)

Created the database :

mysql> create DATABASE shoppingCartDB;
Query OK, 1 row affected (0.00 sec)

mysql> exit

Docker RUN

docker run -p 5000:5000 shoppingms:latest --env shopping-service.configserverurl=http://A.B.C.D:8888 --env shopping-service.eureka.url=http://A.B.C.D:4444/eureka

It is able to fetch the properties from config server. I checked the logs. Error came from this line :

 com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...

In my local environment I am able to use the locally installed MySQL Db with the same connection parameters. However in docker I am getting the exceptions. Where I am going wrong can anyone please help me out.

UPDATE :

After exposing the MySQL container to port 3306, the error stands at now :

2020-09-28 12:07:43.942 [ : ] WARN  [task-1] o.h.e.j.e.i.JdbcEnvironmentInitiator - HHH000342: Could not obtain connection to query metadata : null,  message from server: "Host 'Some-IP' is not allowed to connect to this MySQL server"
     1 --- [         task-1] o.h.e.j.e.i.JdbcEnvironmentInitiator     : HHH000342: Could not obtain connection to query metadata : null,  message from server: "Host 'Some-IP' is not allowed to connect to this MySQL server"

2020-09-28 12:07:49.219 [ : ] WARN  [task-1] o.h.e.j.s.SqlExceptionHelper - SQL Error: 1130, SQLState: HY000
 1 --- [         task-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1130, SQLState: HY000
2020-09-28 12:07:49.225 [ : ] ERROR [task-1] o.h.e.j.s.SqlExceptionHelper - null,  message from server: "Host 'Some-IP' is not allowed to connect to this MySQL server"
 1 --- [         task-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : null,  message from server: "Host 'Some-IP' is not allowed to connect to this MySQL server"

答案1

得分: 1

我建议运行一个 Docker Compose 文件来描述你的应用程序设置。

作为指南,以下是一个用于在给定网络上运行 phpMyAdmin、MySQL 8 和 Tomcat 的 Compose 文件。我已经根据你的应用程序需求进行了猜测:

version: "3.5"
services:
  # 根据你的应用程序进行以下更新
  app:
    image: shoppingms:latest
    restart: always
    ports:
      - 5000:5000
    links:
      - db:db
    environment: 
      - shopping-service.configserverurl=http://A.B.C.D:8888
      - shopping-service.eureka.url=http://A.B.C.D:4444/eureka
    networks: 
      - appnet
  db:
    image: mysql:8.0
    restart: always
    ports:
        - 3306:3306
    command: --default-authentication-plugin=mysql_native_password
    environment:
        MYSQL_DATABASE: mydb
        MYSQL_USER: user
        MYSQL_PASSWORD: user123
        MYSQL_ROOT_PASSWORD: user123
    volumes:
        - ./sql-init:/docker-entrypoint-initdb.d
        - ./mysql/data:/var/lib/mysql
    networks:
        - appnet
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    restart: always
    links:
        - db:db
    ports:
        - 8201:80
    environment:
        MYSQL_USER: user
        MYSQL_PASSWORD: user123
        MYSQL_ROOT_PASSWORD: user123
    networks:
        - appnet
  tomcat:
    image: library/tomcat:9
    restart: always
    links:
        - db:db
    ports:
        - 8081:8080
    volumes:
      - ./tomcat/webapps:/usr/local/tomcat/webapps
      - ./tomcat/logs:/usr/local/tomcat/logs
    networks:
        - appnet

networks:
  appnet:
    name: appnet

在这个应用程序中,我使用一个外部托管的 Tomcat 服务器,并将 Spring Web 应用程序装入容器中。还有各种暴露的端口,以便于外部访问。

你需要根据你的需求对应用程序容器进行配置/调整。

数据库在 DNS 名称为 db 上开放,这也是 phpMyAdmin 使用的名称。

英文:

I would suggest running a docker compose file to describe your application setup.

As a guide line, this is a compose file for running phpMyAdmin, MySQL 8, tomcat on a given network. I have given a guess at your application requirement:

version: "3.5"
services:
  # Update the below for your application
  app:
    image: shoppingms:latest
    restart: always
    ports:
      - 5000:5000
    links:
      - db:db
    environment: 
      - shopping-service.configserverurl=http://A.B.C.D:8888
      - shopping-service.eureka.url=http://A.B.C.D:4444/eureka
    networks: 
      - appnet
  db:
    image: mysql:8.0
    restart: always
    ports:
        - 3306:3306
    command: --default-authentication-plugin=mysql_native_password
    environment:
        MYSQL_DATABASE: mydb
        MYSQL_USER: user
        MYSQL_PASSWORD: user123
        MYSQL_ROOT_PASSWORD: user123
    volumes:
        - ./sql-init:/docker-entrypoint-initdb.d
        - ./mysql/data:/var/lib/mysql
    networks:
        - appnet
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    restart: always
    links:
        - db:db
    ports:
        - 8201:80
    environment:
        MYSQL_USER: user
        MYSQL_PASSWORD: user123
        MYSQL_ROOT_PASSWORD: user123
    networks:
        - appnet
  tomcat:
    image: library/tomcat:9
    restart: always
    links:
        - db:db
    ports:
        - 8081:8080
    volumes:
      - ./tomcat/webapps:/usr/local/tomcat/webapps
      - ./tomcat/logs:/usr/local/tomcat/logs
    networks:
        - appnet

networks:
  appnet:
    name: appnet

In this application I was running a externally hosted tomcat server with Spring webapp volumed into the container. There are various ports exposed as well for ease of external access.

You would need configure/tweak your application container as per your requirement.

The Database is exposed on the DNS name db which is what phpMyAdmin uses.

答案2

得分: 0

可以立即解决问题。

  1. 从docker inspect命令中识别IP地址。
  2. 为该IP创建一个用户。
  3. 需要修改新用户的密码。
  4. 授予用户一些权限。
  5. 退出

现在再次运行您的容器,这次它可以获取连接并成功创建表格。

英文:

Able to resolve the issue now.

 1. Identify the ip address from docker inspect command.
 2. Create an user for that ip.
 3. Need to alter the new user password.
 4. Grant some privileges to the user.
 5. Exit

Now run your container again, this time it could obtain the connections and successfully create the tables.

huangapple
  • 本文由 发表于 2020年9月28日 19:54:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/64101683.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定