Scala Play JDBC可以';在docker容器中运行时,不能连接到MySQL

Scala Play JDBC可以';在docker容器中运行时,不能连接到MySQL,mysql,scala,docker,jdbc,playframework,Mysql,Scala,Docker,Jdbc,Playframework,我正在尝试制作一个scala play web应用程序(RESTful)。我一直在学习SQL连接的play教程,但是我在将带有play应用程序的容器连接到带有mysql容器的容器时遇到了问题。经过大量调试,我意识到scala应用程序在本地运行而不是在docker容器中运行时确实可以工作 来自application.conf的代码 db.default.driver=com.mysql.cj.jdbc.Driver db.default.url="jdbc:mysql://localhost:49

我正在尝试制作一个scala play web应用程序(RESTful)。我一直在学习SQL连接的play教程,但是我在将带有play应用程序的容器连接到带有mysql容器的容器时遇到了问题。经过大量调试,我意识到scala应用程序在本地运行而不是在docker容器中运行时确实可以工作

来自application.conf的代码

db.default.driver=com.mysql.cj.jdbc.Driver
db.default.url="jdbc:mysql://localhost:49160/testdb"
db.default.username="root"
db.default.password="password"
db.default.host="localhost"

# db connections = ((pyhsical_core_count * 2) + effective_spindle_count)
fixedConnectionPool = 17

database.dispatcher {
  executor = "thread-pool-executor"
  throughput = 1
  thread-pool-executor {
    fixed-pool-size = ${fixedConnectionPool}
  }
}
docker-compose.yml

version: "2"

services:
  spades:
    build: ./spades
    depends_on:
      - database
    volumes:
      - ./spades/cardsatra-spades:/home/app
    ports:
      - 49162:9000

  database:
    build: ./database
    ports:
      - 49160:3306
    volumes:
      - ./database/data:/var/lib/mysql:rw
sbt应用程序摘要文件

ARG OPENJDK_TAG=8u232
FROM openjdk:8u232

ARG SBT_VERSION=1.3.7

# Install sbt
RUN \
  curl -L -o sbt-1.3.7.deb https://dl.bintray.com/sbt/debian/sbt-1.3.7.deb && \
  dpkg -i sbt-1.3.7.deb && \
  rm sbt-1.3.7.deb && \
  apt-get update && \
  apt-get install sbt && \
  sbt sbtVersion

EXPOSE 9000

RUN mkdir /home/app
WORKDIR /home/app
COPY cardsatra-spades/entrypoint.sh .

CMD ["/bin/sh", "/home/app/entrypoint.sh"]
FROM mysql:8

# ENV MYSQL_DATABASE stormlight
ENV MYSQL_ROOT_PASSWORD password
ENV MYSQL_USER mysql
ENV MYSQL_PASSWORD password 
ENV DATABASE_HOST db
entrypoint.sh只运行sbt clean和sbt run

数据库dockerfile

ARG OPENJDK_TAG=8u232
FROM openjdk:8u232

ARG SBT_VERSION=1.3.7

# Install sbt
RUN \
  curl -L -o sbt-1.3.7.deb https://dl.bintray.com/sbt/debian/sbt-1.3.7.deb && \
  dpkg -i sbt-1.3.7.deb && \
  rm sbt-1.3.7.deb && \
  apt-get update && \
  apt-get install sbt && \
  sbt sbtVersion

EXPOSE 9000

RUN mkdir /home/app
WORKDIR /home/app
COPY cardsatra-spades/entrypoint.sh .

CMD ["/bin/sh", "/home/app/entrypoint.sh"]
FROM mysql:8

# ENV MYSQL_DATABASE stormlight
ENV MYSQL_ROOT_PASSWORD password
ENV MYSQL_USER mysql
ENV MYSQL_PASSWORD password 
ENV DATABASE_HOST db
scala端点(ommitted该类并导入)->这在GET/news/all路由上

def doSomething: Future[Vector[Newspost]] = Future {
    db.withConnection { conn =>
      var res: Vector[Newspost] = Vector[Newspost]()

      val statement = conn.createStatement
      val resultSet = statement.executeQuery("SELECT * FROM news")


      while(resultSet.next) {
        val id = resultSet.getInt("id")
        val title = resultSet.getString("title")
        val body = resultSet.getString("body")
        val date = resultSet.getString("date")

        res = res :+ Newspost(id, title, body, date)
      }
      res
    }
  }(dec)
当我使用docker compose up数据库运行数据库,并使用sbt运行本地播放应用程序时,端点工作正常并返回Newspost向量

当我通过docker compose up运行这两个应用程序时,我会得到一个巨大的堆栈跟踪

spades_1    | Getting req!
spades_1    | [error] p.a.h.DefaultHttpErrorHandler - 
spades_1    | 
spades_1    | ! @7emkpm006 - Internal server error, for (GET) [/news/all] ->
spades_1    |  
spades_1    | play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.]]
spades_1    |   at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:332)
spades_1    |   at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:251)
spades_1    |   at play.core.server.AkkaHttpServer$$anonfun$2.applyOrElse(AkkaHttpServer.scala:421)
spades_1    |   at play.core.server.AkkaHttpServer$$anonfun$2.applyOrElse(AkkaHttpServer.scala:417)
spades_1    |   at scala.concurrent.impl.Promise$Transformation.run(Promise.scala:453)
spades_1    |   at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:55)
spades_1    |   at akka.dispatch.BatchingExecutor$BlockableBatch.$anonfun$run$1(BatchingExecutor.scala:92)
spades_1    |   at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
spades_1    |   at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:94)
spades_1    |   at akka.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:92)
spades_1    | Caused by: java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.

我省略了大部分scala代码,因为它不在docker中工作。我假设scala代码本身没有问题。

您应该将应用程序指向另一个容器,而不是
localhost
,从系统的角度来看,这意味着相同的“机器”(即相同的容器):


当然,您可以使此设置依赖于环境,以便应用程序在开发模式和docker compose模式下工作。

这是正确的。主机名不应该是localhost,而应该是docker容器名。这是有效的,但只有在docker-compose.yml和db.default.url中将数据库端口更改为3306时才有效。我不知道为什么它不能在端口49160上工作,但至少它现在可以工作了,thanks@mattematt它在端口
49160
上不起作用,因为您将它重新映射到docker compose文件中的
3306
,这意味着内部
49160
端口从外部可见为
3306
端口。@IvanKurchenko简称为
HOST:CONTAINER
,所以我觉得它很好@mattematt我会尝试两件事:1)将端口映射定义为字符串2)使用非临时端口(例如
4444
)。无论哪种方式,
docker ps
和netcat都可能是检查这一点的最佳工具。一个会告诉你容器中暴露了什么,另一个会告诉你是否可以连接到某个东西。