官网地址:http://www.jeecg.com/
开发文档地址:http://doc.jeecg.com/2043873
GitHub地址:https://github.com/zhangdaiscott/jeecg-boot
大致步骤如下:
1.创建MySQL,redis等辅助组件
2.创建jeecg-boot后端应用
3.创建jeecg-vue前端应用
0.说明
1.从GitHub上下载项目的zip压缩包后,解压缩可以看到,ant-design-vue-jeecg是前端模块,jeecg-boot是后端模块
2.按照开发文档上的先在本地配置好前后端所需要的环境。
3.在k8s中创建一个jeecg-boot的名称空间,若无特别说明,以下所有服务都是在该空间创建的
4.部署流程大致是这样的,先在本地把前后端都跑通,然后再创建Dockerfile和.gitlab-ci文件,往gitlab提交代码(事先配置好gitlab-runner),创建镜像,推送到仓库,自动发布更新到k8s上(首次需要用yaml文件创建有关pod,service等)
5.我这里采用了俩git仓库,前端一个,后端一个
1.创建MySQL,redis等辅助组件
说白了也就是创建好MySQL服务,redis服务,后端项目中连接需要使用。
我这里采用的是在k8s中创建的,当然也可以创建普通的那种应用。
以下说的都是在k8s中创建举例的
MySQL和Redis服务,均创建了服务类型是nodeport的service,然后使用宿主机上的软件连接进行测试。等整个项目跑起来运行后再换成service是clusterip的服务类型
MySQL创建创建好后,需要导入相应的sql文件。
sql文件名称:jeecg-boot\db\jeecgboot-mysql-5.7.sql
但是等后端项目运行后会碰到一个问题,有些数据表明是需要大写的,主要是qrtz开头的数据表名
导入sql文件后,把所有qrtz开头的数据表名全部换成大写的数据表名,避免后端项目启动后连接数据库提示有些表不存在
最后启动MySQL和Redis服务。
2.后端项目
0.项目结构
├─jeecg-boot-parent(父POM: 项目依赖、modules组织)
│ ├─jeecg-boot-base(共通模块: 工具类、config、权限、查询过滤器、注解、接口等)
│ ├─jeecg-boot-module-demo 示例代码
│ ├─jeecg-boot-module-system (系统管理权限等功能) -- 默认作为启动项目
│ ├─jeecg-boot-starter(微服务starter模块,不需要微服务可以删掉) (我这边操作的时候给删除了)
│ ├─jeecg-cloud-module(微服务生态模块,不需要微服务可以删掉)(我这边操作的时候给删除了)
1.修改项目配置文件(数据库配置、redis配置)
配置文件: jeecg-boot-module-system/src/main/resources/application-dev.yml
2.启动项目&访问
本地启动:jeecg-boot-module-system/src/main/java/org/jeecg/JeecgSystemApplication.java,右键执行启动。
通过 http://localhost:8080/jeecg-boot/doc.html 访问后台,默认进入swagger文档首页
本地运行
本地启动后的日志显示
3.创建Dockerfile文件
需要说明的是需要的项目只有jeecg-boot-module-system,所以把Dockerfile文件创建在jeecg-boot-module-system根目录下
Dockerfile文件具体文件内容如下:
FROM jdd.io/jre:1.8.275
MAINTAINER 1103324414@qq.com
ADD target/jeecg-boot-module-system-2.4.3.jar app.jar
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar app.jar" ]
说明:开头第一行是使用的基础镜像,创建方式详看地址:https://www.cnblogs.com/sanduzxcvbnm/p/13220054.html
基础镜像中只有jdk环境,其他的都没有了。
4.创建.gitlab-ci文件
这个文件创建在整个项目的根目录下
需要注意的是gitlab-runner使用的构建镜像环境,需要包含开发文档中说的后端项目需要使用的那些软件。
我这边图省事儿,前后端构建项目使用的是同一个构建镜像,包含的软件就比较多了:jdk,maven,curl,docker,nodejs,yarn等,具体构建方式可以看地址:https://www.cnblogs.com/sanduzxcvbnm/p/13220054.html
还有注意的一点,jeecg需要使用到一些私服的依赖,详看地址:http://doc.jeecg.com/2043876
<mirrors>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*,!jeecg,!jeecg-snapshots,!getui-nexus</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
所以在构建刚才的镜像时,添加的maven需要修改以下settings.xml配置文件。
我这边采取的方式是事先准备好已经修改好的settings.xml配置文件,然后在构建过程中copy到镜像中,替换原有的配置文件
FROM alpine:latest
MAINTAINER sandu <1103324414@qq.com>
COPY localtime /etc/localtime
COPY timezone /etc/timezone
RUN echo "https://mirrors.aliyun.com/alpine/latest-stable/main/" > /etc/apk/repositories
RUN echo "https://mirrors.aliyun.com/alpine/latest-stable/community/" >> /etc/apk/repositories
RUN ["apk","update"]
RUN ["apk","add","curl"]
RUN ["apk","add","openjdk8"]
RUN ["apk","add","maven"]
RUN ["apk","add","nodejs"]
COPY settings.xml /usr/share/java/maven-3/conf/settings.xml
RUN ["apk","add","docker"]
构建好这个镜像后,修改gitlab-runner使用的镜像,然后重启gitlab-runner
注意:不能把这个镜像跟后端dockerfile文件中使用的镜像混为一谈,这俩是里面安装的软件不一样
.gitlab-ci.yml文件内容如下:
variables:
DOCKER_DRIVER: overlay2
MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
cache:
paths:
- .m2/repository/
stages:
- package
- build
maven_step:
tags:
- maven
stage: package
script:
- mvn clean package -Dmaven.test.skip=true # 编译整个项目
artifacts:
paths:
- jeecg-boot-module-system/target/*.jar # 注意这行,只要其中一个jar包,供下面的docker使用
only:
- develop
docker_step:
tags:
- docker
stage: build
script:
- export TAG=`date "+%Y%m%d%H%M%S"`
- docker login -u admin -p admin123 jdd.io
- cd jeecg-boot-module-system
- docker build -t jdd.io/demo:$TAG .
- docker push jdd.io/demo:$TAG
only:
- develop
构建的思路如下:先编译打包整个项目,然后切换到所需要jar包的目录下,然后根据这个目录下的Dockerfile文件制作docker镜像,并上传到Nexus镜像仓库,这里指的是jeecg-boot-module-system
流水线上显示的效果,需要事先配置好gitlab-runner
后期可以在增加上自动发布到k8s上,如下这个仅供展示,实际中未操作:(新增加curl一行)
docker_step:
tags:
- docker
stage: build
script:
- export TAG=`date "+%Y%m%d%H%M%S"`
- docker login -u admin -p admin123 jdd.io
- cd jeecg-boot-module-system
- docker build -t jdd.io/demo:$TAG .
- docker push jdd.io/demo:$TAG
- curl -X PUT -H "content-type:application/json" -H "Cookie:KuboardUsername=admin;KuboardAccessKey=4jz66jfsa6t6.5wjsz733f73p5fei4h4fpbmnfp72ytbc" http://192.168.2.163:10080/kuboard-api/cluster/develop/kind/CICDApi/admin/resource/updateImageTag -d '{"kind":"deployments","namespace":"test","name":"web-spring","images":{"jdd.io/demo":"jdd.io/demo:'$TAG'"}}'
only:
- develop
pod启动后的日志展示,里面出现的是pod的地址,因为pod的特性,所以访问后端使用的话,还需要创建一个service,采用clusterip服务类型
以后访问后端,直接使用ClusterIP+服务端口的形式就可以了。
当然可以先创建service,采用NodePort的服务类型,然后通过宿主机IP+NodePort的形式,直接访问后端应用,比如接口文档,查看以下效果,地址:http://宿主机IP:NodePort/jeecg-boot/doc.html
3.创建前端
前端最主要的是使用生成的dist文件夹,这里结合nginx,把两者直接整个进同一个镜像中,这样一来,启动这个容器,nginx直接就启动了,nginx访问路径正好是vue的dist文件夹里面的东西
关于vue配置文件的说明
-
vue.config.js文件中的配置是在本地开发的时候使用的,此处映射地址配置到后台端口即可,如果后台项目名字修改了的话,直接改“/jeecg-boot”
-
.env文件是用来选择项目构建时使用哪个配置文件的,主要是有关.env.development和.env.production文件的,这里写的是哪个,项目采用的就是哪个配置文件,这里写的是NODE_ENV=production,说明采用的是.env.production文件
3.关于.env.production文件中的配置
这个地址应该是配置连接后端项目的,也就是后端项目启动后日志中显示的那个地址。但是在这里做了特殊的设置,主要是跟下面的Dockerfile文件中nginx的配置和后期创建的Ingress有关,稍后再详讲解这个。
直接在前端项目根目录下创建Dockerfile文件,文件内容如下:
# build stage
FROM node:lts-alpine as build-stage # 采用alpine镜像,多阶段构建方式
MAINTAINER 1103324414@qq.com
COPY . /app/ # 把跟目录下所有文件拷贝到上面镜像的/app目录下,该目录不存在的话会自动创建
WORKDIR /app/ # 切换容器中的当前工作目录
RUN npm config set registry https://registry.npm.taobao.org/ && yarn install && yarn run build # 设置nodejs仓库源,安装依赖,打包
# production stage
FROM nginx:stable-alpine as production-stage
# 拷贝dist目录下的所有文件到/usr/share/nginx/html/目录下,不包含dist文件夹
COPY --from=build-stage /app/dist /usr/share/nginx/html/
ENV LANG en_US.UTF-8
# 设置nginx中的配置文件内容
RUN echo "server { \
listen 80; \
location ^~ /jeecg-boot { \
proxy_pass http://10.3.255.203:8080/jeecg-boot/; \
proxy_set_header Host jeecg-boot-system; \
proxy_set_header X-Real-IP \$remote_addr; \
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; \
} \
#解决Router(mode: 'history')模式下,刷新路由地址不能找到页面的问题 \
location / { \
root /usr/share/nginx/html/; \
index index.html index.htm; \
if (!-e \$request_filename) { \
rewrite ^(.*)\$ /index.html?s=\$1 last; \
break; \
} \
} \
access_log /var/log/nginx/access.log ; \
} " > /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
说明:
1.nginx.conf文件中没有server{}块,默认包含/etc/nginx/conf.d/*.conf, 有个默认的default.conf,这里直接替换默认的default.conf了。
2.如下这块是配置的nginx代理后端模块的,proxy_pass中写的地址,端口就是后端项目启动的service服务,ClusterIP+服务端口,详看上面的图
location ^~ /jeecg-boot {
proxy_pass http://10.3.255.203:8080/jeecg-boot/;
proxy_set_header Host jeecg-boot-system;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
}
然后创建.gitlab-ci.yml文件,具体内容如下:
variables:
DOCKER_DRIVER: overlay2
MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
cache:
key: ${CI_BUILD_REF_NAME}
paths:
- node_modules/
stages:
- build
docker_step:
tags:
- docker
stage: build
script:
- export TAG=`date "+%Y%m%d%H%M%S"`
- docker build -t jdd.io/jeecg-vue:$TAG .
- docker login -u admin -p admin123 jdd.io
- docker push jdd.io/jeecg-vue:$TAG
- curl -X PUT -H "content-type:application/json" -H "Cookie:KuboardUsername=admin;KuboardAccessKey=hx35mfx3b7p6.w6wm38cbikdd4yeweexfcsfybd4zmk2s" http://192.168.2.163:10080/kuboard-api/cluster/develop/kind/CICDApi/admin/resource/updateImageTag -d '{"kind":"deployments","namespace":"jeecg","name":"my-vue","images":{"jdd.io/jeecg-vue":"jdd.io/jeecg-vue:'$TAG'"}}'
only:
- develop
构建的思路如下:直接根据这个目录下的Dockerfile文件制作docker镜像,并上传到Nexus镜像仓库,然后自动更新到k8s中(需要事先使用yaml文件创建好对应的pod,下面会讲述)
检查方式是登录进入,查看nginx是否启动,若启动则说明没问题。
gitlab上使用gitlab-runner自动化构建的信息如下:
先配置好gitlab-runner(前后端用的是同一个gitlab-runner)
给前端pod配置一个service,这里也采用的是服务类型是ClusterIP的方式,注意,这里的容器端口就是nginx启动后监听的80端口,服务端口是供下面Ingress域名使用的端口,这里采用80端口,是为了在浏览器中输入域名访问时不用加端口号了
然后再配置一个Ingress,用来供外部访问,这个域名就是前端访问后端的.env.production配置文件中设置需要的,本机电脑上hosts文件需要添加一个解析
集群中任意一台主机ip都可以
本机电脑访问的话直接使用浏览器打开域名:www.demovue.com就可以了。
问题:为啥前端的.env.production配置文件中访问后端的地址需要配置域名,而不是直接配置后端的svc ip地址?
一开始确实是这样配置的,但是在登录页面需要输入验证码,这个验证码是从后端获取的,但是此时客户端是本机浏览器,不是vue, 浏览器中验证码访问的地址是svc ip地址,这肯定是访问不通的
同时结合nginx配置考虑,访问后端是通过nginx代理访问的。
以上两者结合起来,需要配置域名。
浏览器访问vue主页,vue访问后端的时候,不是直接访问后端,而是访问后端时配置的是域名,然后vue又绕道nginx来访问后端。
4.有关yaml文件
1.后端
# cat Deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-demo
namespace: jeecg
labels:
app: my-demo
spec:
replicas: 1
selector:
matchLabels:
app: my-demo
template:
metadata:
labels:
app: my-demo
spec:
containers:
- name: my-demo
image: 'jdd.io/demo:20210421194224'
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
resources:
requests:
cpu: 400m
memory: 600Mi
limits:
cpu: 800m
memory: 800Mi
imagePullSecrets:
- name: regcred
# Service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-demo
namespace: jeecg
spec:
type: NodePort
selector:
app: my-demo
ports:
- port: 8080
targetPort: 8080
nodePort: 30080
- 前端yaml文件
# Deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-vue
namespace: jeecg
labels:
app: my-vue
spec:
replicas: 1
selector:
matchLabels:
app: my-vue
template:
metadata:
labels:
app: my-vue
spec:
containers:
- name: my-vue
image: jdd.io/jeecg-vue:20210421232150
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
resources:
requests:
cpu: 400m
memory: 600Mi
limits:
cpu: 800m
memory: 800Mi
imagePullSecrets:
- name: regcred
# Service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-vue
namespace: jeecg
spec:
type: ClusterIP
selector:
app: my-vue
ports:
- port: 80
targetPort: 80
# Ingress.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
labels:
app: my-demo
k8s.kuboard.cn/name: my-demo
name: my-demo
namespace: jeecg
spec:
rules:
- host: www.demovue.com
http:
paths:
- backend:
serviceName: my-demo
servicePort: 80
path: /
最终效果