使用docker部署springboot项目到服务器
背景
好久没有更新过博客了,没啥的,就是闲的,对,就是闲的,代码敲得比较烦,后端逻辑实在有点绕了,就寻思着不如将项目部署一下,使用docker部署到服务器上。首先说一下自己的感受吧,截止到现在吧,感觉docker部署springboot的项目有点麻烦,真心不如使用alibaba cloud toolkit这个插件部署方便,配置好sh文件之后,一键部署,不过确实通过docker部署到服务器上,确实能学到很多知识。
安装docker
安装docker的话,感觉没什么可以赘述的,百度一篇都可以,这里贴出我使用的----->>>>在Ubuntu中安装Docker和docker的使用。docker部署springboot项目应该有两种方法,一种是在项目里面新建一个docker的文件夹,然后再docker文件夹下新建一个Dockerfile的文件,然后再写入指令,还需要再pom文件里添加插件依赖等,比较麻烦,简单的话,应该就是这种,大概流程就是:使用maven打包->编写Dockerfile文件->将jar包和Dockerfile文件存到服务器上->build到docker里面->找镜像->run镜像
maven打包
切记,打包之前一定要测试一遍,一定要测试一遍,一定要测试一遍。
我docker部署好了之后发现项目一直启动不起来,当然排除了端口没有开放的问题,但是就是没有起来,然后自己就在target的目录下输入指令java -jar demo.jar
发现出现这个错误:spring-xxx-xxx-0.0.1-SNAPSHOT.jar中没有主清单属性,然后解决的方法是在pom上添加插件就行:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
好了,进入正规,maven打包的话,各种方法都可以,只要能在target文件夹下找到生成的jar文件就行。
我使用的是mvn install -DskipTests
,啰嗦几句,这段指令在根目录下执行。
编写Dockerfile文件
#FROM openjdk:8-jdk-alpine
#ADD *.jar app.jar
#ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
# Docker image for springboot file run
# VERSION 0.0.1
# Author: eangulee
# 基础镜像使用java
FROM java:8
# 作者
MAINTAINER yamon <yamon@gmail.com>
# VOLUME 指定了临时文件目录为/tmp。
# 其效果是在主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp
VOLUME /tmp
# 将jar包添加到容器中并更名为app.jar
ADD linkai-0.0.1-SNAPSHOT.jar app.jar
# 运行jar包
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-jar","/app.jar"]
#VOLUME 指定了临时文件目录为/tmp。其效果是在主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp。该步骤是可选的,如果涉及到文件系统的应用就很有必要了。/tmp目录用来持久化到 Docker 数据文件夹,因为 Spring Boot 使用的内嵌 Tomcat 容器默认使用/tmp作为工作目录
#项目的 jar 文件作为 “app.jar” 添加到容器的
#ENTRYPOINT 执行项目 app.jar。为了缩短 Tomcat 启动时间,添加一个系统属性指向 “/dev/./urandom” 作为 Entropy Source
#
#如果是第一次打包,它会自动下载java 8的镜像作为基础镜像,以后再制作镜像的时候就不会再下载了。
注释都在里面放着呢,百度出来的基本上都这这几个。
jar包和Dockerfile文件上传到服务器上
直接使用xftp上传就行。
打包成镜像
进入到/opt/java/linkai中,输入指令:docker build -t linkai .
这里有个点,表示运行上下文。最后linkai是镜像名字。
创建容器并运行容器
docker run -d -p 80:8080 --name linkai linkai
80指的是服务器端口,8080指的是容器内的端口,也就是jar包中application.properties中的port端口值。
访问
输入ip地址就可以访问了。
后记
部署过程有点艰辛,原因在于部署好了,因为各种原因,项目里面代码必须修改,说个常见的我遇到的问题,那就是使用thymeleaf中,使用ModelAndView的setViewName的时候,开头不能以/开头。举个例子:
/**
* 打印页面
* @param id 进货单id
* @return 页面
*/
@RequestMapping(value = "/update/{id}",method = RequestMethod.GET)
public ModelAndView update2Page(@PathVariable Integer id){
ModelAndView modelAndView = new ModelAndView();
//查出来商品和进货单信息
InputOrderUpdateDto inputOrderUpdateDto = inputorderService.selectInputOrderDto4UpdateById(id);
modelAndView.addObject("inputOrder",inputOrderUpdateDto);
//不能写成这样 modelAndView.setViewName("/admin/business/inputOrder/update/update");
modelAndView.setViewName("admin/business/inputOrder/update/update");
return modelAndView;
}
要不会报找不到或者不存在这个html模板。然后我就只能一个一个改,改完了之后必须重新打包,然后重新运行镜像,这点就有点小恶心了,如果使用alibaba cloud toolkit的话,直接push到服务器上就可以直接运行了。
这个过程,不下三遍,所以想总结一下今晚常用的docker指令:
首先先得分清镜像和容器,镜像就相当于一个应用,然后容器就相当于与将应用放到一个机器上运行,所以说,就必须先有应用然后才能使用机器,所以创建镜像在前,使用镜像放到容器内在后。
先创建镜像,也就是上述的打包镜像指令docker build -t linkai .
,在images中就可以找到,使用docker images
docker images:查看所有的镜像
docker pull 镜像名[:tag]:下载指定镜像,比如上面的mysql镜像,输入docker pull mysql:5.6。
docker rmi -f 镜像id:这里首次讲到镜像id,可以看到镜像id就是上面的IMAGE ID,那么长,使用tab键也不能补全,不用慌,直接输入前3个就可以,比如删除linkai这个镜像,输入33f就行了。这个指令比较常用
docker rmi -f $(docker images -aq):删除所有的镜像
到此为止,只是将打包成为镜像,也就是产生了应用,如果将应用放到机器中运行,那就需要运行镜像了:docker run -d -p 80:8080 --name linkai linkai
docker ps -a:查看所有的容器
简单解释一下,command是在dockerfile里面写过的,部署项目之后,有几点需要注意,STATUS:当前的状态,Exited(1)非正常终止,大概率是程序出错,Exited(0)应该是手动停止或者正常程序运行终止,Exited(143)这个反正也是终止的意思,但是没怎么查,不大清楚。PORTS:容器内和服务器的端口映射。
docker stop Container Id:停止容器
docker rm Container Id:删除指定容器,但是如果正在运行的话,不能删除,两种解决策略,一种使用这个指令docker rm -rf Container Id,或者使用停止容器的指令,然后再删除。
docker run -d IamgeId :后台运行镜像。
docker logs -t 容器Id:查看日志,重要
讲的就这么些吧,说一下现在仍然存在的问题,如果项目用到redis的话,不适用。mysql的话,应该也不适用,因为我用的是阿里云的数据库,所以不用担心这个。还有就是如果项目中有上传文件到服务器上的话,应该也不能用,具体原因可以自己考虑一下为什么不能。如果讲的有什么问题,可以评论在评论区,谢谢阅读。
码字不易,请点个赞。