SE3353-assignment10
简单总结一下这次作业。使用Docker-Compose封装SpringBoot应用、Nginx、MySQL、MongoDB和Redis。
1 | 任务要求: |
整体框架可以参考这个博客,但是真正debug起来前前后后也是花了一两周时间,只能说还是docker用得太少了,以及docker集群中的错误定位在没有经验的情况下还是非常痛苦的,包括思维的“连续性”这件事情,因为每次拾起来这个任务总需要花费一些建立去retrieve之前的记忆,但每次能够挤出来的时间又是碎片时间,导致retrieve记忆的效率很低。相关代码在这个仓库。
SpringBoot的Docker化
也就是把一个Spring Boot工程打包成Docker镜像,这件事情网上有各种各样奇奇怪怪的教程让我去安装什么插件,配置什么端口。这些都是不必要的事情。首先明确我们整个过程打包出来的就只有一个单纯的jar包,这个jar包是平台无关的,我们只需要根据这个jar包封装成一个docker镜像并且启动起来实例就可以了。所以其实我们只需要在bookstore_backend-1.0-SNAPSHOT.jar的相同目录下新建一个Dockerfile文件,写入如下代码:
1 | #基于哪个镜像 |
MySQL的Docker部署
理论上这是一个非常非常非常常见的应用场景,但是就是在这一步卡了我非常久非常久的时间。
首先是,因为是从容器中启动MySQL,最开始容器中是没有数据库的,所以需要有一个初始化过程。所以先要从我们原先的生产环境中把数据库拿出来,这里就直接使用这篇博客提到的全量备份方法:
1 | mysqldump -uroot -p123123 --databases bookstore>./init/init.sql |
但是根据教程把在docker-compose中绑定- ./init:/docker-entrypoint-initdb.d后,启动以后还是没有bookstore数据库。根据这篇回答,在command中添加–init-file /docker-entrypoint-initdb.d/init.sql,这才让我真正能够在启动容器的时候初始化我的数据库。
接下来就是需要让我们的SpringBook容器真正连上这个容器中的MySQL,这才算是打通了集群化部署的工作流程。
总体踩过的坑如下:
在docker-compose的MySQL的environment中,必须设置MYSQL_ROOT_HOST: ‘%’,根据MySQL官网的叙述,如果不设置这一条,MySQL容器只会允许‘root‘@’localhost’,也就是容器内部的查询请求通过,但是我们配置出来的MySQL显然是需要让内网的别的容器访问的。
在docker-compose的MySQL的environment的MYSQL_ROOT_PASSWORD中,似乎不支持纯数字密码。(至少我设置123456登录不上去,设置为纯字母密码才可以)。
在docker-compose的MySQL的environment中,可能需要设置MYSQL_DATABASE。这个变量指定了我们在创建镜像时需要创建的数据库,如果我们还设置了MYSQL_USER,会同时授予User访问这个数据库的权限。
在Spring Boot的application.properties中,如果我们之前设置的是访问路径是‘jdbc:mysql://localhost:3306/bookstore?autoReconnect=true&useSSL=false‘,我们需要把localhost修改为docker-compose中service的名字,否则这样SpringBoot会调用localhost自己容器中的3306端口,但是它自己的容器里是没有MySQL的。
在Debug过程中,其实看到最多的是如下的报错信息:
1
2
3
4
5
6java.sql.SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
#此处省略几十行
at com.bookstore.Application.main(Application.java:123) ~[classes/:na]
Caused by: com.mysql.cj.exceptions.CJException: Access denied for user 'root'@'localhost' (using password: YES)
#此处省略几十行
... 50 common frames omitted
现在回过头来看其实当时主要还是看到那么多行报错一直在搜第一行的错误原因,而中间这一段才是真正的原因,也就是本机尝试登录root账户失败,那显然就是密码错误。
总体的和MySQL相关的配置文件如下:
1 | app_db: |
其余部分的容器化
其他的部分(包括MongoDB,Nginx,Redis,Neo4j)的容器部署大差不差,这些一共加起来可能也就花了半小时时间。主要还是配置第一个MySQL的时候踩了太多太多的坑。
最后放一些结果图。
我们可以看到Nginx确实把请求轮询分发给了两台Server。
并且在响应的结果中,我们确实看到了MySQL和MongoDB组装成功响应。
SE3353-assignment10