解决的问题
docker中的springboot项目访问docker中的mysql和mongo
-
MongoDB连接报错
org.springframework.data.mongodb.UncategorizedMongoDbException: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-256, userName='admin', source='pet', password=
, mechanismProperties= }; nested exception is com.mongodb.MongoSecurityException: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-256, userName='admin', source='pet', password= , mechanismProperties= } at com.zxmt.app.AppApplicationTests.contextLoads(AppApplicationTests.java:72) Caused by: com.mongodb.MongoSecurityException: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-256, userName='admin', source='pet', password= , mechanismProperties= } at com.zxmt.app.AppApplicationTests.contextLoads(AppApplicationTests.java:72) Caused by: java.lang.IllegalArgumentException: Prohibited character at position 0 at com.zxmt.app.AppApplicationTests.contextLoads(AppApplicationTests.java:72) 跳过SpringBoot打包测试
先看一下最开始的配置
-
application.yml
spring: datasource: url: jdbc:mysql://localhost:3306/pet?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false driver-class-name: com.mysql.cj.jdbc.Driver username: root password: 123456 data: mongodb: host: localhost port: 27017 username: admin password: 123456 database: pet
docker 安装mysql与mongo
将项目打包成为jar包,并上传到服务器
打包的时候,项目会进行测试,然后会出现一个问题。就是mongodb连接报错,这个问题是由于我们使用分开写配置文件,host,port,database这种造成的,具体原因我也不太清楚,有人说是jdk版本问题,所以直接换成uri模式
org.springframework.data.mongodb.UncategorizedMongoDbException: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-256, userName='admin', source='pet', password=, mechanismProperties=}; nested exception is com.mongodb.MongoSecurityException: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-256, userName='admin', source='pet', password=, mechanismProperties=}
at com.zxmt.app.AppApplicationTests.contextLoads(AppApplicationTests.java:72)
Caused by: com.mongodb.MongoSecurityException: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-256, userName='admin', source='pet', password=, mechanismProperties=}
at com.zxmt.app.AppApplicationTests.contextLoads(AppApplicationTests.java:72)
Caused by: java.lang.IllegalArgumentException: Prohibited character at position 0
at com.zxmt.app.AppApplicationTests.contextLoads(AppApplicationTests.java:72)
spring:
datasource:
url: jdbc:mysql://localhost:3306/pet?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
data:
mongodb:
# 重点:mongodb://用户名:密码@localhost:27017/数据库名
uri: mongodb://admin:123456@localhost:27017/pet
在jar文件同级目录新建Dockerfile,内容如下
FROM java:8-alpine
ADD app-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
然后在当前目录执行(最后有一个点,表示上下文 ):docker build -t pet-app .
因为docker中运行着mysql和mongo,所以我们直接开始运行pet-app这个自己打包的镜像
dokcer run -d -p 8080:8080 --name pet-app pet-app
-d 表示后台运行, --name 表示取一个别名 ,最后一个pet-app表示刚才的镜像名称
OK问题来了
你以为一切很顺利,但是你访问接口会发现错误
Error querying database. Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.\n### The error may exist in com/zxmt/app/mapper/AgreementMapper.java (best guess)\n### The error may involve com.zxmt.app.mapper.AgreementMapper.selectById\n### The error occurred while executing a query\n### Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up."
这个问题就是,docker中的springboot没能通过localhost:3306访问到数据库,同时mongo也是访问不到
解决方案1:直接将localhost改为服务器地址就可以了,相当于docker中的服务通过网络访问服务器端口,服务器再访问docker。(⊙o⊙)…这个决绝办法有点low
解决方案2:使用docker中的--link参数
-
先修改配置文件。将原来的主机地址都取一个别名例如下面的mysql,mongo
spring: datasource: url: jdbc:mysql://mysql:3306/pet?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false driver-class-name: com.mysql.cj.jdbc.Driver username: root password: 123456 data: mongodb: uri: mongodb://admin:123456@mongo:27017/pet
-
因为改了这个配置文件,打包的时候会进行测试,(你想你都写成jdbc:mysql://mysql:3306这样了,测试能通过吗)所以现在需要配置跳过测试(在pom的properties中加代码)
true 还是Dockerfile打包成镜像
-
最后是通过镜像启动容器的代码!!!!重点
docker run -p 8080:8080 -d --link=mysql:mysql --link=mongo:mongo --name pet-app pet-app
--link:前面的mysql表示启动的容器的名称,后面是别名名称对应上面的配置文件中的mysql
jdbc:mysql://mysql:3306/pet?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false
当然mongo也是一样。。
再把之前的错误启动方式贴一次对比一下
# 错误的 dokcer run -d -p 8080:8080 --name pet-app pet-app #正确的 docker run -p 8080:8080 -d --link=mysql:mysql --link=mongo:mongo --name pet-app pet-app