本文將帶你們從一臺全新的 CentOS 服務器開始,部署一套完整的先後端分離項目。操做步驟很是詳細,新手友好型文章~html
後端技術棧:SpringCloud 微服務架構 + Redis + RabbitMQ + MySql;前端
前端技術棧:Vue + ElementUI;java
部署工具:後端用 Docker 容器化部署,並把命令封裝成腳本自動執行;前端用 Nginx 作代理。node
系統版本爲:CentOS 7.6 64位。mysql
要對遠程服務器進行操做,首先要連上服務器才行。打開命令行工具,輸入如下命令,再輸入服務器實例的密碼,便可遠程鏈接到服務器。linux
ssh root@xxx.xx.xx.xx
複製代碼
@
以後是服務器的公網 ip,假如服務器 ip 地址爲:120.456.78.123,那麼鏈接服務器的命令爲:nginx
ssh root@120.456.78.123
複製代碼
敲回車以後會讓輸入密碼,輸入正確的密碼便可。c++
Docker 容器化部署的優勢就很少說了,直接上乾貨如何安裝 Docker。redis
下面直接把代碼框裏的命令拷貝到命令行執行就能夠。spring
先移除舊版本(若是有):
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
複製代碼
安裝一些必要的工具:
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
複製代碼
添加軟件源信息:
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
複製代碼
更新 yum 緩存:
sudo yum makecache fast
複製代碼
安裝 Docker-ce:
sudo yum -y install docker-ce
複製代碼
啓動 Docker 後臺服務
sudo systemctl start docker
複製代碼
測試運行 hello-world(這步可要可不要,目的是驗證身份安裝 Docker 成功,若是成功會打印出 Hello World)
docker run hello-world
複製代碼
拉取 mysql5.7 版本的鏡像
docker pull mysql:5.7
複製代碼
運行 MySql
docker run -p 3306:3306 --name mysql -v $PWD/conf:/etc/mysql/conf.d -v $PWD/logs:/logs -v $PWD/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
複製代碼
命令說明:
- -p 3306:3306:將容器的 3306 端口映射到主機的 3306 端口。
- -v $PWD/conf:/etc/mysql/conf.d:將主機當前目錄下的 conf/my.cnf 掛載到容器的 /etc/mysql/my.cnf。
- -v $PWD/logs:/logs:將主機當前目錄下的 logs 目錄掛載到容器的 /logs。
- -v $PWD/data:/var/lib/mysql :將主機當前目錄下的data目錄掛載到容器的 /var/lib/mysql 。
- **-e MYSQL_ROOT_PASSWORD=123456:**初始化 root 用戶的密碼。
注意在運行以前切換到合適的目錄,由於 MySql 容器映射到本機的目錄是映射的當前目錄的相對目錄。好比當前目錄爲 /root/abc
,那執行完上面的命令後,會在 /root/abc
下建立 MySql 掛載出來的目錄和文件。
也能夠直接執行運行命令,若是系統檢測到沒有安裝此鏡像,則會拉取安裝,再運行。
下載並運行 redis:4.0.8
:
docker run -p 6379:6379 -t -dit redis:4.0.8
複製代碼
跟上面同樣也是直接執行運行命令安裝並運行 rabbitmq:3.7.7
:
docker run -d --hostname my-rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3.7.7-management
複製代碼
到此部署微服務後端項目的前期環境準備工具已經作完。若是要部署前端還須要安裝 Nginx,這個在前端部署的章節再講。
部署後端須要作的工做有兩個,一個是修改每一個微服務模塊的配置文件 application.yml
,另外一個是編寫 Dockerfile
。
先看目錄結構:
一共有 5 個模塊,其中 common
是純 java 代碼用於各模塊公共代碼的提取,剩下四個每一個是一個獨立的微服務模塊,因此咱們要部署 eureka
、user
、education
、gateway
四個模塊,也就是最後會運行四個獨立的 docker 容器。
具體的業務邏輯就不作過多說明了,本文只講部署。
application.yml
爲了本地調試和服務器部署互不影響,咱們把原來的 application.yml
拆分爲三個文件:
application.yml
:總配置,指定應該用下面哪一個配置application-dev.yml
:開發環境配置application-pro.yml
:生成環境配置另外爲了方便,把 Dockerfile 也放到同級目錄下。如圖:
下面是三個配置文件的代碼:
application.yml
spring:
profiles:
active: pro
複製代碼
application-dev.yml
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
server:
port: 8899
spring:
application:
name: education
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://127.0.0.1/edu?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
jpa:
show-sql: true
# 若是字段值爲null則不返回
jackson:
default-property-inclusion: non_null
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
redis:
port: 6379
database: 0
host: 127.0.0.1
password:
jedis:
pool:
max-active: 8
max-wait: -1ms
max-idle: 8
min-idle: 0
timeout: 5000ms
複製代碼
application-pro.yml
eureka:
client:
service-url:
defaultZone: ${SPRING-CLOUD-EUREKA-ZONE}
instance:
prefer-ip-address: true
server:
port: 8899
spring:
application:
name: education
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://${SPRING-CLOUD-MYSQL-HOST}/${SPRING-CLOUD-DB-NAME}?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
jpa:
show-sql: true
# 若是字段值爲null則不返回
jackson:
default-property-inclusion: non_null
rabbitmq:
host: ${SPRING-CLOUD-RABBIT-MQ-HOST}
port: 5672
username: guest
password: guest
redis:
port: 6379
database: 0
host: ${SPRING-CLOUD-REDIS-HOST}
password:
jedis:
pool:
max-active: 8
max-wait: -1ms
max-idle: 8
min-idle: 0
timeout: 5000ms
複製代碼
這個項目配置比較全,redis、rabbitMQ、mysql、jpa 都有配置。
dev 跟 pro 的配置差很少,只是把 dev 中的 localhost
、127.0.0.1
這兩個本地的地址,換成了諸如 ${SPRING-CLOUD-EUREKA-ZONE}
、${SPRING-CLOUD-RABBIT-MQ-HOST}
等變量。
那這些變量是在哪設置的呢?待會兒編寫 Dockerfile 的時候就能夠看到,會在 Dockerfile 裏設置這幾個變量爲環境變量,當啓動 Docker 容器的時候,程序就會讀取到 Dockerfile 中設置的值並應用到項目中。
下面是 education
模塊的 Dockerfile
FROM java:8
VOLUME /tmp ADD education.jar app.jar RUN bash -c 'touch /app.jar'
ENV SPRING-CLOUD-EUREKA-ZONE http://123.456.789.10:8761/eureka/
ENV SPRING-CLOUD-MYSQL-HOST 123.456.789.10
ENV SPRING-CLOUD-DB-NAME edu
ENV SPRING-CLOUD-RABBIT-MQ-HOST 123.456.789.10
ENV SPRING-CLOUD-REDIS-HOST 123.456.789.10
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] EXPOSE 8899
複製代碼
簡單的解釋下每句話的做用
FROM java:8
: 指定基礎鏡像,必須爲第一個命令
VOLUME /tmp
: 用於指定持久化目錄
ADD education.jar app.jar
: 將本地文件education.jar
添加到容器中並命名爲app.jar
。注意這裏的education.jar
要換成你本身項目打包出來的 jar 包名字,若是你打的包名字叫abc.jar
,那應該這麼寫:ADD abc.jar app.jar
。
RUN bash -c 'touch /app.jar'
: 在鏡像容器中執行的命令,運行 jar 包。
ENV ***
: 這幾行以 ENV 開頭的是設置環境變量,還記得上面application-pro.yml
文件裏的那幾個${}
變量嗎?就是在這裏設置的。把該填地址的地方都換成這臺服務器的公網 ip 地址,本配置假設你服務器的地址是123.456.789.10
,用的時候把這個地址換成你本身服務器地址便可。
ENTRYPOINT ***
: 配置容器,使其可執行化。
EXPOSE 8899
: 對外暴露 8899 端口。這個端口要和項目的配置文件中server.port
設置的端口一致。
總結一下,Dockerfile 文件你要改的,只有三個地方:
application-pro.yml
的配置進行設置EXPOSE 8899
改爲你項目的端口號再貼一個模塊的 Dockerfile 做對比:
FROM java:8
VOLUME /tmp ADD gateway.jar app.jar RUN bash -c 'touch /app.jar'
ENV SPRING-CLOUD-EUREKA-ZONE http://123.456.789.10:8761/eureka/
ENV SPRING-CLOUD-REDIS-HOST 123.456.789.10
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] EXPOSE 8888
複製代碼
按照這種方法,把每一個須要打包的微服務項目的 Dockerfile 寫好。
配置好三個 applicaiton.yml
和 Dockerfile(其實打包這一步用不到 Dockerfile),在項目的根目錄下執行如下命令打包:
mvn clean package -Dmaven.test.skip=true
複製代碼
看到控制檯輸出 SUCCESS 則打包成功
打完的包在 項目目錄/target
裏,如圖:
檢查一下 jar 包的大小,若是是好幾十 M 就沒啥問題,若是是幾百 K 那就是打包配置有問題,檢查 pom.xml
文件的 <build>
標籤配置是否正確。
附 <build>
配置:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<finalName>education</finalName>
</build>
複製代碼
寫完 Dockerfile 文件還要執行命令打包成 image 鏡像,還須要運行起容器,兩行代碼雖然很少但每次寫仍是麻煩,把它封裝成一個 sh
腳本,每次直接運行腳本省時省力。
新建 education_deploy.sh
文件,把兩行代碼放進去:
docker build -t education .
docker run -p 8899:8899 -t -dit --restart=always education
複製代碼
注意第一行最後有個點 .
,若是你想把打出來的鏡像名叫 abc
,對外暴露的端口是 6666
,則應該這樣寫:
docker build -t abc .
docker run -p 6666:6666 -t -dit --restart=always abc
複製代碼
新建一個文件夾,併爲每一個微服務模塊新建一個文件夾用於存放 jar 包、Dockerfile 和自動化部署文件,目錄結構如圖:
把 back_end 這個文件夾總體壓縮,壓縮命令爲:
tar -cvf back_end.tar ./back_end
複製代碼
執行完後會在目錄下看到 back_end.tar
壓縮文件。
使用 ssh 命令登陸到服務器,根目錄下新建一個 edu
文件夾,進入這個文件夾,查看當前目錄,記住這個目錄
//新建文件夾 edu
mkdir edu
//進入到 edu 文件夾內
cd edu
//查看當前目錄,會輸出:/root/edu
pwd
複製代碼
記住你要傳到服務器的位置:/root/edu
,再回到本機剛纔壓縮 back_end.tar
文件的目錄,執行如下命令把 back_end.tar
發送到服務器的 /root/edu
目錄下:
scp back_end.tar root@123.456.789.10:/root/edu
複製代碼
上傳完以後,在服務器解壓
tar -xvf back_end.tar
複製代碼
而後依次進入到各個模塊的文件夾內,執行 sh 腳本
sh ./education_deploy.sh
複製代碼
都運行完以後後端微服務就部署完啦!
部署完還要檢驗是否部署正確,先從 Docker 開始檢查,最後在瀏覽器輸入接口地址看可否調通。
下面的命令都在 CentOS 服務器上執行。
查看當前運行的容器,看 mysql、redis、rabbitMQ 和你本身的項目是否運行
docker ps
複製代碼
想進入到容器中查看日誌:
docker logs 容器id
複製代碼
好比想查看容器id爲 378af204f7bc 的容器日誌,應該執行:
docker logs 378af204f7bc
複製代碼
若是容器運行了很長時間,將會產生很是多的日誌,直接使用 docker logs
會把全部日誌都打印出來,可不能夠只打印最後多少行或者從某個時間以後的日誌呢?固然能夠。
查看指定時間後的日誌,只顯示最後100行:
docker logs -f -t --since="2019-10-24" --tail=100 CONTAINER_ID
複製代碼
只打印最後50行日誌:
docker logs --tail=50 容器id
複製代碼
查看最近30分鐘的日誌:
docker logs --since 30m 容器id
複製代碼
查看某時間以後的日誌:
docker logs -t --since="2019-10-24T13:23:37" CONTAINER_ID
複製代碼
查看某時間段日誌:
docker logs -t --since="2019-10-24T13:23:37" --until "2019-10-25T12:23:37" CONTAINER_ID
複製代碼
中止容器
docker stop 容器id
複製代碼
查看全部容器(包括已經中止的)
docker ps -a
複製代碼
從新啓動容器(容器被中止了,但還未被刪除)
docker start 容器id
複製代碼
若是項目有改動,最好把以前的容器、鏡像都刪掉,再運行新的容器。
先中止容器
docker stop 容器id
複製代碼
再刪除容器
docker rm 容器id
複製代碼
查看 image 鏡像
docker images
複製代碼
刪除鏡像
docker rmi 鏡像id
複製代碼
先把前端項目打包,壓縮爲 tar 文件,發送到服務器上,在服務器解壓。
要用 nginx 作代理須要先安裝 nginx
先下載安裝基礎庫
yum -y install gcc gcc-c++ autoconf pcre pcre-devel make automake
yum -y install wget httpd-tools vim
複製代碼
安裝 nginx
sudo yum install nginx
複製代碼
nginx 的配置文件目錄
nginx主配置文件
/etc/nginx/nginx.conf
/etc/nginx
/etc/nginx/conf.d
/etc/nginx/conf.d/default.conf
複製代碼
咱們來看 nginx.conf
默認的配置是什麼樣
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2 default_server;
# listen [::]:443 ssl http2 default_server;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# location / {
# }
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
}
複製代碼
修改 nginx.conf
的 server 節點,咱們依然監聽 80端口,改 server_name
爲你的域名,而後修改 location
,root
爲前端文件所在目錄,index
爲入口文件。
location / {
root /root/edu/front_end/;
index index.html index.htm;
}
複製代碼
只改這兩處便可,別的地方不要動。
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name www.abc.cn abc.cn;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
root /root/edu/front_end/;
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
複製代碼
改完保存成功以後,檢查 nginx 配置,結果出現 successful 表示配置文件沒有語法錯誤
nginx -t -c /etc/nginx/nginx.conf
複製代碼
從新加載配置
nginx -s reload -c /etc/nginx/nginx.conf
複製代碼
從新加載配置時有時會報錯:nginx: [error] open() "/var/run/nginx.pid" failed (2: No such file or directory)
解決方法:依次執行下面兩行代碼
sudo nginx -c /etc/nginx/nginx.conf
nginx -s reload
複製代碼
用瀏覽器訪問域名,報 403 錯誤,要具體看究竟是哪裏出錯了能夠查看 nginx 錯誤日誌,錯誤日誌在哪放着呢? nginx.conf
文件裏指明瞭:error_log /var/log/nginx/error.log;
用 cat 命令查看文件內容
cat /var/log/nginx/error.log
複製代碼
若是報了 Permission denied,有很大多是當前登陸用戶跟 nginx.conf
文件第一行聲明的用戶不匹配。
connect() to 127.0.0.1:8000 failed (13: Permission denied)....
複製代碼
將 user nginx;
改成 user root;
再次從新加載配置通常就能夠解決。
以上就是部署先後端的所有內容,大佬們有問題能夠在評論區交流。