欢迎访问我们的原创博客网站:http://www.czquan.cn/#/resource-detail/35402
《绝对的干货,前后端分离方式的项目使用docker-compose到底是如何部署的?》
halo,大家好,久违了,时隔一个月我又回来啦,前面我们介绍了什么是docker-compose的常用命令,以及docker的五种网络模式与应用场景。
本章主要讲解如何使用docker-compose部署企业级前后端分离方式的单体项目,本章将贯穿前面所有学习过的知识点,将以《成长圈知识付费后台管理平台》项目作为讲解。
本项目使用人人开源的后端和前端项目做的二次开发,前端采用vue2.0开发,后端使用spring boot微服务框架,首先看看我们最终的项目展示页面。
部署步骤如下:
我们在前门第四章节已经讲过如何部署,本章节不再做讲解,本项目直接拿来用即可。
在编写之前我们先说下我们对应的文件目录结构,是这样的
docker-compose.yaml
czqmall-platform
—Dockerfile
czq_portal
—Dockerfile
在后端项目根目录创建dockerfile文件,然后编写如下内容
FROM openjdk:8-jre #指定我们后端容器的基础镜像为安装好jdk8的基础linux系统的镜像
WORKDIR /app #指定容器的工作目录,也就是后面的CMD指令执行的目录为/app目录,没有会自动创建
#定义变量,如下变量都可以通过上一个目录的docker-compose.yaml参数化传入值,可以先写好默认值
ENV SERVER_PORT 8088 # 定义微服务启动的端口号
ENV ENV dev # 定义环境名 默认为启用dev的配置
ENV MYSQL_HOST "" # mysql服务的ip地址和端口
ENV MYSQL_DATABASE "" #mysql连接的数据库名称
ENV MYSQL_USER "" # mysql用户名
ENV MYSQL_PASSWORD "" #mysql密码
COPY ./czqmall-platform/target/*.jar /app # 将打好的jar包复制到目标linux系统的app目录,注意如果是以docker-compose执行部署,那么这里的路径是相对于docker-compose文件的位置开始的,因为我们这里目录层级是将项目和docker-compose文件的位置同一个目录,需要进入项目内部才能找到jar包文件
EXPOSE $SERVER_PORT # 暴露容器端口 这里就是暴露对应微服务启动的端口
ENTRYPOINT ["sh", "-c"]
CMD ["java -jar *.jar"] # 启动微服务
在这里的 FROM openjdk:8-jre
,意思是我们部署的后端服务项目将放到一个基于java8镜像的轻量级的linux系统上,你可以把它当做是一个安装好jdk8的最基础的linux系统的镜像,然后当我们创建了容器后,对应的linux系统也就安装好了,并且对应的项目也拷贝到我们的linux系统的app目录中了。
以上的一些环境变量其实你可以把他看成是作为linux系统上配置的环境变量,,这样程序内部可以自动读取到当前系统中的环境变量的值,比如在linux系统上我们配置的jdk环境变量,程序里也可以读取到,后端服务启动端口获取的变量为 SERVER_PORT,对应的启用配置为 ENV,启动的mysql连接信息MYSQL开头的环境变量名等 在程序中都有获取。
#1、基于node11镜像打包前端项目
#基于node11镜像,且别名为build(这个步骤用于打包前端项目)
FROM node:11.15.0-alpine AS build
#定义环境变量,可以由docker-compose传入,下面先定义默认值
ARG BASE_API
ARG PORT
WORKDIR /opt/app/web
#复制当前前端项目到对应的工作目录
COPY ./czq_portal /opt/app/web
# npm的一些配置,用于打包的一些配置,比如指定npm镜像仓库之类的
RUN npm config set unsafe-perm true
RUN npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/ --global
RUN npm config set registry https://registry.npm.taobao.org --global
RUN npm config set disturl https://npm.taobao.org/dist --global
RUN npm install node-sass
#进入前端项目内安装依赖
RUN cd /opt/app/web && \
npm install
#给指定变量赋值并打包 最终会输出静态文件到前端项目的dist目录
RUN BASE_API=$BASE_API PORT=$PORT npm run build
#进入打包好的静态文件目录,并输出文件,可以查看
RUN cd /opt/app/web/dist && ls
#2、基于caddy反向代理工具部署前端项目
#基于caddy镜像实现容器内部反向代理,可以将上面的环境变量参数传入,也可以使用上面的别名
#当然也可以使用基于nginx镜像进行反向代理
FROM abiosoft/caddy
#定义接收上一步的环境变量参数
ARG BASE_API
ARG PORT
#复制上一步镜像打包好的静态文件 到 本caddy容器的/var/www目录
COPY --from=build /opt/app/web/dist /var/www/
#将反向代理配置文件复制到caddy对应的目录,相当于nginx的nginx.conf文件,用于描述url路径跳转规则,这一点理解尤为重要,也是难点
COPY ./czq_portal/Caddyfile /etc/Caddyfile
这一步就是我们在前端请求接口的时候我们会将就用前端的域名作为后端服务的地址跳转,但是会加上一个后缀/server。
这里我们可以先创建一个Caddyfile文件在前端项目的根目录,首先我们预先设定好前端的启动端口是801,并且给后端反向代理的路径是/server,然后代理到后端服务的ip是物理机ip,端口就是后端服务的端口为8080,并且后端有要求带上servlet-context路径为api。
:801 {
index index.html
root /var/www/
}
:801/server {
proxy / http://192.168.178.128:8080/api {
transparent
websocket
}
}
下图所示便是后端的接口统一路径,需要带上api前缀,所以上面我们配置反向代理的时候,我们会加上对应的api后缀
比如后面我们如果部署了项目,可以从前端请求的地址查看请求后端接口的路径:
我们可以看到请求的后端接口地址上有加上/server,其实这个参数就是我们在打包前端镜像的时候docker-compose传递的,也就是前端请求的接口直接就是和前端服务的域名一致,再加上对应的/server转到我们前端的容器中,然后让前端容器中的caddy做一个反向代理,到对应的后端服务的ip、端口、以及api路径。
version: '2'
services:
# 后端服务
czq-platform:
build:#构建镜像(注意,如果本地仓库没有czq-platform:latest镜像才会构建,有此镜像不会再构建,除非删掉本地镜像,所以后面再次发版需要将本地镜像删除再部署,这样才会重新构建新的镜像)
context: .
dockerfile: ./czqmall-platform/Dockerfile #如果dockerfile文件和docker-compose.yaml文件不在同一个文件夹则需要指定
restart: always #自动重启
image: czq-platform:latest #定义构建的镜像名
ports: # 配置物理机暴露公网的端口和容器端口的映射
- "8080:8099"
environment:
- SERVER_PORT=8099 #指定微服务启动的端口号为8099
- ENV=prod #指定环境名为prod
- MYSQL_HOST=192.168.178.128:3308 # mysql服务的ip地址和端口,ip地址可以先写宿主机linux服务器的ip
- MYSQL_DATABASE=czqmall #mysql连接的数据库名称
- MYSQL_USER=root #mysql用户名
- MYSQL_PASSWORD=CZQ666 #mysql密码,查看第四章部署的配置
volumes:
- '/usr/share/zoneinfo/Asia/Shanghai:/etc/localtime' #指定数据库时区为东八区
entrypoint:
- /bin/sh
- -c
command:
- "java -jar /app/*.jar" # 执行启动命令
# 前端服务
czq-portal:
build: #构建镜像(注意,如果本地仓库没有czq-portal:latest镜像才会构建,有此镜像不会再构建,除非删掉本地镜像,所以后面再次发版需要将本地镜像删除再部署,这样才会重新构建新的镜像)
context: .
dockerfile: ./czq-portal/Dockerfile #如果dockerfile文件和docker-compose.yaml文件不在同一个文件夹则需要指定
restart: always #自动重启
image: czq-portal:latest #定义构建的镜像名
environment:
- PORT=801
ports: # 配置物理机暴露公网的端口和容器端口的映射
- "801:801"
volumes:
- '/etc/localtime:/etc/localtime'
部署前先将项目都拉取到我们的根目录,先创建一个整体的项目文件夹,然后里面依次放入前端项目代码、后端项目代码、以及docker-compose.yaml三个文件。
当然注意我们的前后端项目名称的下划线和中线不一样哦,这里就是为了让大家明白这个地方相对位置的重要性。
上面所说的docker-compose指定的dockerfile目录位置如下对应
Dockerfile里面的copy命令的目录位置如下对应
1、安装jdk和mvn(已安装请忽略)
参考:https://blog.csdn.net/wsjzzcbq/article/details/123902173
2、打包
进入后端项目根目录执行 mvn clean package
命令进行打包操作,打包后会提示BUILD SUCCESS。
打包后我们可以看到jar包文件在target目录:
表以及表的数据均在后端项目的db目中,自己下载后执行对应的mysql.sql即可。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g3COrIoE-1670993102929)(null)]
部署前先清理掉docker-compose以及Dockerfile中所有的注释,比如ENV环境变量的配置、copy命令等后面不能加注释,不然会有一些值不对,会导致一些奇葩的问题。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JjCoxI2D-1670993102970)(null)]
在docker-compose所在目录执行docker-compose up -d
命令
它会自动先拉取基准镜像,然后再构建本地的前后端镜像,再启动容器。
依次从上往下部署service,后端构建好镜像后就会拉取前端的基础镜像
我们可以看到最终2个项目均部署成功,可以查看对应的2个done,以及一个提示,如果你要使用新的镜像需要使用docker-compose build命令,如果不想用之前的缓存,可以加上–no-cache参数,比如docker-compose build --no-cache serviceName
,其实也可以在本地将镜像删除后直接运行docker-compose up -d也可以达到重新构建镜像的目的。
也就是说当我们程序有更新需要发版,我们就需要重新构建前后端镜像再启动容器,不然默认它还是以上一次的版本为准继续部署。
使用docker ps命令查看部署的项目
1、第一次启动发现问题1 (MYSQL端口写错)
我们可以使用日志输出命令查看前后端服务是否启动成功,我们发现数据库没有连接上,这样我们检查了,是数据库端口错了,改为对应的正确的3308端口即可,具体的端口还需要看你自己的mysql的端口哦。
docker logs -ft --tail 200 c7d8bdf930e2
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eFzWnssK-1670993103071)(null)]
我们修改好对应的docker-compose文件后,再去停掉服务,再执行up启动服务,这里不用删除镜像重新构建镜像,因为我们只是修改的docker-compose的参数配置,没有修改项目的代码和Dockerfile,如果修改了程序以及Dockerfile是都需要重新构建镜像的哦。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AzlJ7oXd-1670993103422)(null)]
2、再次尝试发现问题2 (MYSQL密码的变量名写错)
我们发现启动后又有错误,这次是密码错了,我们可以看下是不是docker-compsoe配置错误?还是说多了空格,发现都不是,那我们再去看看代码,结果发现我们代码定义的变量名和我们的docker-compose给的密码变量名不一致,所以这里我们改为一致就可以了,为了方便呢,我们就不改代码了,修改docker-compose即可。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oxM44HpK-1670993103306)(null)]
修改好后继续重试,终于成功啦~ ,我们也可以发现启动的端口是8099,说明我们传递的环境变量生效。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KBqnlHzb-1670993103265)(null)]
3、查看前端是否启动成功
只要看到有serving http:xxx 就代表部署成功啦,其他警告信息是我们没有配置https,这个可以不用管,后面会介绍如何单独使用caddy2加上免费的https域名证书。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yBNVFiqQ-1670993103342)(null)]
这个时候其实已经可以通过宿主机ip和前端的端口访问了,账号密码均为admin
参考步骤:https://blog.csdn.net/t8116189520/article/details/81909574
参考上述步骤后其他完善操作:
1、配置开机启动nginx
编辑文件/etc/rc.d/rc.local 在后面添加内容
vi /etc/rc.d/rc.local
内容 /usr/local/nginx/sbin/nginx
ll查看下rc.local文件,如果不是绿色表示没有执行权限,则执行指令chmod +x /etc/rc.d/rc.local
2、配置全局nginx指令
编辑/etc/profile文件vi /etc/profile
在末尾处添加
PATH=$PATH:/usr/local/nginx/sbin
export PATH
执行source /etc/profile
指令
找到我们的nginx的conf文件,然后配置前后端的反向代理
vi /usr/local/nginx/conf/nginx.conf
location /{
proxy_pass http://127.0.0.1:801;
}
保存后重启nginx
nginx -s reload
然后我们直接在我们系统上使用物理机的ip地址就可以访问啦,这个时候就不用输入801端口了,当然一般我们后期会配置对应的域名,这里我们可以在本机的dns上绑定一个,比如:czq.com,然后我们再去修改下nginx的配置的server_name 为这个域名地址即可。
保存后我们可以直接访问czq.com即可
我们也可以看到请求的接口地址:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-daI05w7R-1670993103384)(null)]
后端:https://gitee.com/xiejaijie/czqmall-platform.git
前端:https://gitee.com/xiejaijie/czqmall_admin.git
这一章节就到这啦,下一章节我们将进入CICD持续集成部署实战:《如何搭建jinkins CICD流水线自动化部署微服务应用》,我们下一章节再见,敬请期待~~
其他更多文章可以访问我们的官方网站:www.czquan.cn,或者关注我们的公众号哟:
包括后期陆续要更新的文章有很多很多ing:
1、认识Docker、使用docker部署应用
2、认识Dockerfile,如何用Dockerfile构建镜像
3、容器间如何通信? 以及如何实现数据挂载?
4、认识docker-compose、如何使用docker-compose部署应用
5、介绍docker-compose的常用命令以及Docker五种网络模式与应用场景
6、使用docker-compose部署前后端分离方式的应用
7、如何搭建jinkins CICD流水线自动化部署微服务应用
8、如何搭建gitlab CICD流水线自动化部署微服务应用
9、如何使用kubeadm快速部署一个K8s集群
10、如何使用kubeadm搭建高可用的K8s集群
11、K8S基础知识讲解
12、利用CICD流水线自动化部署微服务应用到K8S集群
…