docker 容器中 运行 时,Scala Play JDBC 无法连接到 MySQL
Scala Play JDBC can't connect to MySQL when running in a docker container
我正在尝试制作一个 scala play 网络应用程序 (RESTful)。我一直在关注 SQL 连接的播放教程,但我无法将带有播放应用程序的容器连接到带有 mysql 容器的容器。经过大量调试后,我意识到当 运行 在本地而不是在 docker 容器中时,scala 应用程序确实可以工作。
代码来自 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 应用程序 docker文件
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"]
entrypoint.sh 只需 运行s sbt clean 和 sbt 运行
数据库docker文件
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 端点(省略了 class 和导入)-> 这是在 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 构建数据库并使用 sbt 在本地播放应用程序时 运行 端点正常工作并且 returns Newspost 矢量
当我 运行 通过 docker 组合两个应用程序时,我得到一个巨大的堆栈跟踪
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: 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.applyOrElse(AkkaHttpServer.scala:421)
spades_1 | at play.core.server.AkkaHttpServer$$anonfun.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(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
,这意味着从系统的角度来看相同 "machine"(即相同的容器):
db.default.url="jdbc:mysql://database:49160/testdb"
您当然可以使此设置依赖于环境,以便应用程序在开发模式和 docker-compose
模式下工作。
我正在尝试制作一个 scala play 网络应用程序 (RESTful)。我一直在关注 SQL 连接的播放教程,但我无法将带有播放应用程序的容器连接到带有 mysql 容器的容器。经过大量调试后,我意识到当 运行 在本地而不是在 docker 容器中时,scala 应用程序确实可以工作。
代码来自 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 应用程序 docker文件
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"]
entrypoint.sh 只需 运行s sbt clean 和 sbt 运行
数据库docker文件
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 端点(省略了 class 和导入)-> 这是在 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 构建数据库并使用 sbt 在本地播放应用程序时 运行 端点正常工作并且 returns Newspost 矢量
当我 运行 通过 docker 组合两个应用程序时,我得到一个巨大的堆栈跟踪
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: 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.applyOrElse(AkkaHttpServer.scala:421)
spades_1 | at play.core.server.AkkaHttpServer$$anonfun.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(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
,这意味着从系统的角度来看相同 "machine"(即相同的容器):
db.default.url="jdbc:mysql://database:49160/testdb"
您当然可以使此设置依赖于环境,以便应用程序在开发模式和 docker-compose
模式下工作。