一、引言
? ? ? ? 最近公司在海外上云服務(wù)器,作者自己也搞了云服務(wù)器去搭建部署系統(tǒng),方便了解整體架構(gòu)和系統(tǒng)的生命周期,排查解決問題可以從原理側(cè)進(jìn)行分析實(shí)驗(yàn)。雖然用的云不是同一個(gè),但是原理都是相通的。
二、選型
? ? ? ? 作者選用的是騰訊云,沒別的原因,就是便宜加牌子大。
????????阿里云肯定是更好一些的,不管是服務(wù)售后還是服務(wù)器內(nèi)核和操作系統(tǒng)都是比較活躍的,畢竟作者以前公司用的就是阿里云,了解一些。
????????不過以前都是和運(yùn)維溝通排查問題,作者自己只能看到一些服務(wù)器監(jiān)控和運(yùn)維的截圖,這對(duì)于了解整個(gè)云服務(wù)架構(gòu)體系的生命流程是不太友好的。
? ? ? ? 操作系統(tǒng)選擇了CentOS7.6-Docker20,畢竟linux的底層是必須的,目前的容器環(huán)境也是服務(wù)的基礎(chǔ)。
? ? ? ? 基本參數(shù)如下,沒必要太好
- CPU - 2核 內(nèi)存 - 4GB
- 系統(tǒng)盤 - SSD云硬盤 60GB管理快照
- 流量包 - 500GB/月(帶寬:5Mbps)
三、系統(tǒng)搭建部署
? ? ? ? 作者準(zhǔn)備把springboot用Maven打包,jar包拿到docker容器運(yùn)行
3.1、后端
? ? ? ? 后端是SpringBoot,SSM框架,代碼就不貼了,作者寫了個(gè)小程序給家里人用的。
3.2、打包
? ? ? ? 這一步很麻煩,打出來的包很小,作者當(dāng)時(shí)還沒意識(shí)到問題,本地java -jar運(yùn)行一下,報(bào)錯(cuò)了。顯示no main manifest attribute, in /**.jar,問了一下chatGpt,這就很扯,做了這么久的SpringBoot,他里面的application怎么可能不是字段設(shè)置為主類的呢。
? ? ? ? 作者有找了網(wǎng)上的一些文章,有的說是打包的時(shí)候沒有設(shè)置入口類,pom的build重新設(shè)置一下。
<build>
<plugins>
<!-- maven-compiler-plugin 插件配置 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- maven-jar-plugin 插件配置 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>**.Application</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<!-- 其他插件... -->
</plugins>
</build>
? ? ? ? 然后出現(xiàn)了新的錯(cuò)誤:Caused by: java.lang.ClassNotFoundException: org.springframework.boot.SpringApplication
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
? ? ? ? 跟chatgpt拉扯了許久,還是沒找到正確的pom,又找了朋友看以前做的項(xiàng)目,其實(shí)很簡(jiǎn)單的po,完全依賴spring自動(dòng)打包發(fā)現(xiàn)
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
? ? ? ? 打包之后有60幾M大小,之前只有幾百k,所以很明顯了,再次本地運(yùn)行java -jar,顯示成功,通過Localhost也可以訪問里面的接口
?3.3 部署
? ? ? ? 部署系統(tǒng)jar之前,需要先把數(shù)據(jù)庫(kù)部署好,不然根本運(yùn)行不起來。
1、部署mysql
? ? ? ? 這里安裝的的是mysql5.7,習(xí)慣了這個(gè)版本
????????下載MySQL 5.7的Docker鏡像:docker pull mysql:5.7
????????下載完成后,可以運(yùn)行以下命令來創(chuàng)建并運(yùn)行MySQL容器:docker run --name mysql?-e MYSQL_ROOT_PASSWORD=<password> -p 3306:3306 -d mysql:5.7
????????創(chuàng)建一個(gè)名為`mysql`的容器,并將MySQL的默認(rèn)端口3306映射到主機(jī)的3306端口。將`<password>`替換密碼。
????????檢查MySQL容器是否正在運(yùn)行:docker ps -a
????????如果看到`mysql`容器正在運(yùn)行,說明MySQL已經(jīng)成功安裝并運(yùn)行在Docker中。
????????如果MySQL容器未運(yùn)行,啟動(dòng)它:docker start mysql
????????登錄到MySQL:docker exec -it mysql mysql -u root -p
????????檢查MySQL服務(wù)器的運(yùn)行狀態(tài):service mysql status
????????啟動(dòng)它:service mysql start
????????作者在這中間還走了一些彎路,一開始不想設(shè)置用戶名密碼,結(jié)果導(dǎo)致他自動(dòng)生成了一串,作者還不知道密碼是什么,又進(jìn)去修改密碼,最后還生成了兩個(gè)root賬號(hào),一個(gè)權(quán)限是*一個(gè)是localhost,導(dǎo)致后面jar運(yùn)行出了問題。
2、部署服務(wù)
? ? ? ? 騰訊云界面上有個(gè)SFTP的文件可視化,作者一開始不知道,還準(zhǔn)備搞市面上的一些文件傳輸軟件,畢竟jar包需要傳輸?shù)竭h(yuǎn)程服務(wù)器。
? ? ? ? 首先要?jiǎng)?chuàng)建一個(gè)Dockerfile,這個(gè)文件沒有后綴的,在服務(wù)器窗口建好文件夾之后
? ? ? ? 輸入:vi?Dockerfile
? ? ? ? 從vi界面搭建i編輯,自動(dòng)創(chuàng)建文件,寫完內(nèi)容之后點(diǎn)擊esc退出編輯狀態(tài),再點(diǎn)擊:wq退出文件并且保存。
????????Dockerfile里面內(nèi)容:
# 基礎(chǔ)鏡像使用java
FROM openjdk:8-jdk-alpine
# VOLUME 指定了臨時(shí)文件目錄為/tmp。
# 其效果是在主機(jī) /var/lib/docker 目錄下創(chuàng)建了一個(gè)臨時(shí)文件,并鏈接到容器的/tmp
VOLUME /tmp
ADD test-provider-service-0.0.1.jar /test-provider-service.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/test-provider-service.jar"]
1. `FROM openjdk:8-jdk-alpine`:指定使用OpenJDK 8的Alpine Linux作為基礎(chǔ)鏡像。
2. `VOLUME /tmp`:指定將主機(jī)的`/var/lib/docker`目錄與容器的`/tmp`目錄進(jìn)行掛載,用作臨時(shí)文件目錄。
3. `ADD test-provider-service-0.0.1.jar /test-provider-service.jar`:將當(dāng)前目錄下的`test-provider-service-0.0.1.jar`文件復(fù)制到容器的根目錄,并將其重命名為`test-provider-service.jar`。
4. `ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/test-provider-service.jar"]`:指定容器啟動(dòng)時(shí)要執(zhí)行的命令。這里是運(yùn)行Java應(yīng)用程序的命令,使用`java`命令執(zhí)行`test-provider-service.jar`文件。
? ? ? ? 然后把jar傳入服務(wù)器,jar要和Dockerfile在一個(gè)文件夾里面。
? ? ? ? 創(chuàng)建docker鏡像:docker build -t **?.
? ? ? ? 這個(gè).是指使用當(dāng)前文件夾,所以要先cd到j(luò)ar所在的文件夾,**就是指容器的名字。
? ? ? ? 運(yùn)行容器:docker run -d -p 5006:5006**
? ? ? ? 用的是宿主機(jī)5006端口,容器的5006也是作者springboot用的端口,默認(rèn)springboot是用8080的,這個(gè)要在配置文件設(shè)一下
3、問題排查解決
3.1、root拒絕
? ? ? ? docker ps -a看一下容器狀態(tài),誒嘿,退出來了exit,說明jar有問題,但是docker logs ** 有看不到日志,那就加個(gè)日志打印。
public class Application {
public static void main(String[] args) {
try{
SpringApplication.run(Application.class, args);
} catch (Throwable t) {
System.out.println(t);
throw t;
}
}
}
? ? ? ?先得把之前的容器和鏡像刪除,然后重新生成,刪除容器需要用容器id或者名稱,在docker ps -a中可以看到:docker rm **
? ? ? ? 刪除鏡像:docker rmi **? ? ? ??
????????爆出來的是:access denied for user 'root'@'ip' (using password: YES)??
? ? ? ? 一開始還以為是配置錯(cuò)了賬號(hào)密碼,在本地又跑了一下,但是很明顯沒有問題,
????????看了一下mysql,在MySQL的user表中,每個(gè)用戶都有一個(gè)唯一的組合鍵,由用戶名(User)和主機(jī)名(Host)組成。這意味著即使用戶名相同,只要主機(jī)名不同,就會(huì)被視為不同的用戶。我猜測(cè)的是root這個(gè)%會(huì)攔截所有的root訪問,因?yàn)樵诒镜赜脀orkBench去鏈接顯示的也是拒絕。但是%的root不是我設(shè)置的密碼,所以得加一個(gè)新的用戶密碼。
root | localhost
root | %
????????創(chuàng)建一個(gè)具有相同權(quán)限的新用戶,但允許從任何主機(jī)訪問MySQL服務(wù)器:
????????CREATE USER 'new_user'@'%' IDENTIFIED BY 'password';GRANT ALL PRIVILEGES ON *.* TO 'new_user'@'%' WITH GRANT OPTION;
3.2、鏈接mysql失敗
? ? ? ? 再次運(yùn)行鏡像爆出了不一樣的錯(cuò)誤:
Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]: Unsatisfied dependency expressed through method 'sqlSessionFactory' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [com/alibaba/druid/spring/boot/autoconfigure/DruidDataSourceAutoConfigure.class]: Invocation of init method failed; nested exception is com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
? ? ? ? 很明顯是mysql的鏈接問題,但是為什么會(huì)出現(xiàn)這種問題,問一下chatgot
? ? ? ? ?說的很官方,沒有什么實(shí)際作用,但是原理是相同的,要么是驅(qū)動(dòng)程序問題,要么是網(wǎng)絡(luò)問題,如果是驅(qū)動(dòng)程序應(yīng)該不可能出現(xiàn)本地運(yùn)行成功,服務(wù)器失敗。
????????那么就要思考服務(wù)器的docker容器和本地運(yùn)行到底有什么區(qū)別,作者想到的是mysql和服務(wù)jar運(yùn)行在兩個(gè)容器當(dāng)中,本地訪問服務(wù)器的mysql是通過公網(wǎng)ip,那么在服務(wù)器jar里面的配置是使用127.0.0.1(localhost)去鏈接mysql,那么是不是不能直接使用localhost去鏈接。
? ? ? ? 因?yàn)樵品?wù)器的容器不一定在同一個(gè)宿主機(jī)上面,即使在同一個(gè)宿主機(jī),分配端口維度也可能是容器,這個(gè)就看每個(gè)云廠商怎么設(shè)置的規(guī)則了。
? ? ? ? 帶著這樣的猜測(cè),作者把配置文件改為使用內(nèi)網(wǎng)ip,結(jié)果成功了。
文章來源:http://www.zghlxwxcb.cn/news/detail-662314.html
?四、總結(jié)
????????通過自己安裝部署云服務(wù)器上的系統(tǒng),作者對(duì)于整個(gè)系統(tǒng)架構(gòu)有了更多了解,實(shí)踐出真知,對(duì)于技術(shù)工具實(shí)驗(yàn)和底層原理排查都有幫助。文章來源地址http://www.zghlxwxcb.cn/news/detail-662314.html
到了這里,關(guān)于云服務(wù)器-Docker容器-系統(tǒng)搭建部署的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!