使用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的話,應該也不適用,因為我用的是阿里雲的數據庫,所以不用擔心這個。還有就是如果項目中有上傳文件到服務器上的話,應該也不能用,具體原因可以自己考慮一下為什么不能。如果講的有什么問題,可以評論在評論區,謝謝閱讀。
碼字不易,請點個贊。