Docker撰写Spring Boot无法连接到mysql db

时间:2019-09-23 09:58:51

标签: java spring-boot docker docker-compose

我有连接到mysql数据库的spring boot应用程序。如果我以经典方式在本地运行它,则效果很好。但是,当我尝试对其进行dockerise时-数据库成功启动,但应用程序看不到数据库。

我的Dockerfile:

FROM openjdk:11-jdk-slim
ADD start-local.sh /start-local.sh
RUN chmod +x start-local.sh
ENTRYPOINT [ "sh", "-c", "./start-local.sh" ]

我的start-local.sh(我添加了它,以便我的应用程序等待数据库启动):

#!/bin/sh

echo "Waiting for the database server to start"
echo "********************************************************"
apt-get update && apt-get install -y netcat
while ! nc -z mysql 3306; do sleep 3; done
echo "******** Database Server has started"
echo "Starting account service"
java -jar /mnt/service-2.4.0.jar

最后是我的docker-compose.yml文件:

version: '2'
services:
  mysql:
    image: mysql:5.7.23
    environment:
      - MYSQL_ROOT_PASSWORD=root
    entrypoint:
      sh -c "echo 'CREATE DATABASE IF NOT EXISTS books;  CREATE DATABASE IF NOT EXISTS notifications' > /docker-entrypoint-initdb.d/init.sql;/usr/local/bin/docker-entrypoint.sh --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --sql_mode="""
    ports:
      - "3306:3306"

  account_app:
    image: service_img
    environment:
      - "SPRING_PROFILES_ACTIVE=local"
    ports:
      - "8083:8083"
    volumes:
      - "/build/libs/:/mnt"

我执行的操作:

  • 首先,我建立我的service_img
  • 然后我执行docker-compose up。 在日志中,我在应用程序启动日志之后看到数据库启动日志,然后出现错误:
  

| 2019-09-23 09:51:14.006调试[帐户服务,,,] 286 --- [
  main] c.m.l.c.c.d.p.DatasourceConfiguration:创建数据源
  account_app_1 | 2019-09-23 09:51:14.014 INFO [帐户服务,,,]   286 --- [main] com.zaxxer.hikari.HikariDataSource:   HikariPool-1-正在启动... account_app_1 | 2019-09-23 09:51:15.222   错误[帐户服务,,] 286 --- [main]   com.zaxxer.hikari.pool.HikariPool:HikariPool-1-异常   在池初始化期间。 account_app_1 | account_app_1 |   com.mysql.cj.jdbc.exceptions.CommunicationsException:通讯   链接失败account_app_1 | account_app_1 |最后发送的数据包   成功到服务器的时间是0毫秒前。司机还没有   从服务器接收到任何数据包。 account_app_1 |在   com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:835)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.jdbc.ConnectionImpl。(ConnectionImpl.java:455)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:240)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:199)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15]发送的最后一个数据包   成功到服务器的时间是0毫秒前。司机还没有   从服务器接收到任何数据包。 account_app_1 |在   com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:835)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.jdbc.ConnectionImpl。(ConnectionImpl.java:455)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:240)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:199)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:136)   〜[HikariCP-3.2.0.jar!/:na] account_app_1 |在   com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:369)   〜[HikariCP-3.2.0.jar!/:na] account_app_1 |在   com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:198)   〜[HikariCP-3.2.0.jar!/:na] account_app_1 |在   com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:467)   〜[HikariCP-3.2.0.jar!/:na] account_app_1 |在   com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:541)   〜[HikariCP-3.2.0.jar!/:na] account_app_1 | ... 206共   框架省略account_app_1 |造成原因:   com.mysql.cj.exceptions.CJCommunicationsException:通信链接   失败account_app_1 | account_app_1 |最后发送的数据包   成功到服务器的时间是0毫秒前。司机还没有   从服务器接收到任何数据包。 account_app_1 |在   java.base / jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native   方法)〜[na:na] account_app_1 |在   java.base / jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)   〜[na:na] account_app_1 |在   java.base / jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)   〜[na:na] account_app_1 |在   java.base / java.lang.reflect.Constructor.newInstance(Constructor.java:490)   〜[na:na] account_app_1 |在   com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:151)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:167)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:91)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.NativeSession.connect(NativeSession.java:152)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:955)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:825)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |
  ...省略了214个常见框架account_app_1 |造成原因:   java.net.ConnectException:连接被拒绝(连接被拒绝)   account_app_1 |在   java.base / java.net.PlainSocketImpl.socketConnect(本机方法)   〜[na:na] account_app_1 |在   java.base / java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:399)   〜[na:na] account_app_1 |在   java.base / java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:242)   〜[na:na] account_app_1 |在   java.base / java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:224)   〜[na:na] account_app_1 |在   java.base / java.net.SocksSocketImpl.connect(SocksSocketImpl.java:403)   〜[na:na] account_app_1 |在   java.base / java.net.Socket.connect(Socket.java:591)〜[na:na]   account_app_1 |在   com.mysql.cj.protocol.StandardSocketFactory.connect(StandardSocketFactory.java:155)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |在   com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:65)   〜[mysql-connector-java-8.0.15.jar!/:8.0.15] account_app_1 |
  ...省略了217个通用框架account_app_1 |

有什么建议吗?

3 个答案:

答案 0 :(得分:1)

运行组合“堆栈”时,docker使用其自己的DNS机制。

这意味着,如果您在account_app容器内对主机名mysql执行DNS查询,则查询将返回名为mysql的容器的IP地址(可能前缀为堆栈名称)

简而言之:将您的Spring应用程序配置为连接到不在localhost上但在mysql上的mysql数据库,

您可能可以设置一些环境变量来配置它。

答案 1 :(得分:0)

对端口映射有一个误解:您将所有流量从主机端口3306传递到容器端口3306,但这不是双向的。

要处理您的情况,如果您使用的是Linux(在Windows和Mac上不起作用),则可以在docker-compose.yml中添加此配置,以允许容器使用主机服务。

network_mode: "host"

否则,您可以将本地MySql设置为接受来自外部IP的连接,并将容器数据库指向您的IP地址。

请注意,此解决方案仅在本地开发计算机上才能正常工作,我强烈建议在任何生产环境中都避免这种情况。

答案 2 :(得分:0)

我认为您使用“ localhost”作为mysql服务器主机名,

jdbc:mysql://localhost:3306

尝试将其更改为

jdbc:mysql://host.docker.internal:3306

您不能在docker容器内进行localhost。 最好的方法是将jdbc url作为环境变量传递。

SPRING_DATASOURCE_URL=jdbc:mysql://host.docker.internal:3306/code_master

请检查此sh文件的最后5行https://github.com/keaz/code_master/blob/develop/build_docker.sh