超硬核:从零到一部署指南

938 阅读9分钟

封面.png

本文使用的服务器是Centos,内核版本为:CentOS Linux release 7.9.2009 (Core)

看完本文,你将收获到:

Redis的安装与配置
✅Docker的安装与配置
✅MySQL的安装与配置
✅jdk的安装与配置
✅Nginx的安装与配置
✅后端、前端包部署
✅后端的启动脚本编写
✅Nginx的相关配置内容

安装Redis

下载

  • 更新yum包管理器
yum update -y
  • 安装redis
 wget https://download.redis.io/releases/redis-7.4.1.tar.gz
  • 下载好后将压缩包移动到相应的目录下,例如:/home/redis/
  • 解压
tar -xvf redis-7.4.1.tar.gz -C /home/redis/

编译

  • 检测gcc有没有安装
rpm -q gcc

// 如果没安装需要安装

yum -y install gcc
  • 进行编译
// 注意,需要进入主目录,/home/redis/redis-7.4.1
cd /home/redis/redis-7.4.1
  
// 指定编译的目录
make && make PREFIX=/usr/local/redis install

修改配置

  • 进入编译后的目录,并且创建etc目录
cd /usr/local/redis

mkdir etc
  • 拷贝编译前的src目录下的几个文件到编译后的bin目录下
cd /home/redis/redis-7.4.1/src

cp mkreleasehdr.sh /usr/local/redis/bin/
cp redis-check-aof /usr/local/redis/bin/
cp redis-check-rdb /usr/local/redis/bin/
cp redis-sentinel /usr/local/redis/bin/
  • 拷贝文件redis.conf到etc目录下
cd /home/redis/redis-7.4.1

cp redis.conf /usr/local/redis/etc/
  • 修改redis.conf 310行
vim /usr/local/redis/etc/redis.conf

// 打开后,设置显示函数
:set nu
// 将no改成yes
daemonize yes

  • 配置环境变量
vim ~/.bash_profile

// 追加如下内容

# Redis目录
export REDIS_HOME=/usr/local/redis/
  
# 将redis的bin目录加入到环境变量中
PATH=$PATH:$HOME/bin:$REDIS_HOME/bin
  • 使配置生效
source ~/.bash_profile

启动

  • 服务脚本安装

Redis的服务器安装脚本安装文件是: /home/redis/redis-7.4.1/utils/

# 进入utils目录
cd /home/redis/redis-7.4.1/utils/

# 执行install_server.sh 
./install_server.sh 

运行结果

解决方案:把install_server.sh 的第 77~84 行注释掉

再次运行./install_server.sh,全部回车即可

  • 查看redis启动情况
ps -ef | grep redis

通过 install_server.sh 这个服务脚本的安装,可以保证redis随系统的启动而启动,即使系统重启了也会帮我启动redis

  • 启动

上面我们把服务脚本安装以后,redis就已经启动了,也可以通过下面命令启动

# redis将以非控制台运行
redis-server /usr/local/redis/etc/redis.conf

# 查看redis进程
ps -ef | grep redis

如果提示:

WARNING Memory overcommit must be enabled! Without it, a background save or replication may fail under low memory condition. Being disabled, it can also cause failures without low memory condition, see github.com/jemalloc/je… To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.

意思是:

必须启用内存复用!没有它,在内存不足的情况下,后台保存或复制可能会失败。如果被禁用,它也可能导致故障,但不会造成低内存条件,请参阅github.com/jemalloc/je…。要解决此问题,请添加“vm.Overcommit_memory = 1”到/etc/sysctl.conf中,然后重新启动或运行命令“sysctl vm. conf”。Overcommit_memory =1’才能生效

解决:

1.首先,打开 sysctl.conf 文件,使用以下命令

vim /etc/sysctl.conf

2.按 i 键进入编辑模式,在配置文件中添加以下配置

vm.overcommit_memory = 1

3.按 Esc 键,退出编辑模式,输入 :wq 命令,保存退出

4.执行以下命令

sysctl vm.overcommit_memory=1

5.重启redis,发现已经没有警告提示信息了

测试

  • 检测
redis-cli

set hello world

get hello

  • 关闭

可以在redis-cli中输入 "SHUTDOWN"来关闭redis

或者查找对应进程杀掉

修改配置

# 设置可以访问redis服务的ip
bind 0.0.0.0

# 设置redis的访问端口
port 6379

# 设置redis密码
requirepass 123abc!@

注意:这里的bind配置,是一定要修改后,外部工具才可以连接成功

并且开放相应的防火墙/安全组,这个时候外部就可以进行连接了

安装Docker

为什么要安装docker?因为使用的数据库可能存在多个版本的原因,所以使用docker管理较为方便

手动安装

卸载旧版本

较旧的 Docker 版本称为 docker 或 docker-engine 。如果已安装这些程序,请卸载它们以及相关的依赖项。

yum remove docker \
    docker-client \
    docker-client-latest \
    docker-common \
    docker-latest \
    docker-latest-logrotate \
    docker-logrotate \
    docker-engine

设置仓库

安装所需的软件包。yum-utils 提供了 yum-config-manager ,并且 device mapper 存储驱动程序需要 device-mapper-persistent-data 和 lvm2

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

安装最新版本的 Docker Engine-Community 和 containerd

sudo yum install docker-ce docker-ce-cli containerd.io

如果提示您接受 GPG 密钥,请选是,输入y即可

启动Docker

systemctl start docker
或
service docker start

验证是否安装成功

docker version

Docker 需要用户具有sudo权限,为了避免每次都输入sudo,可以把用户加入Docker用户组(官方文档)

sudo usermod -aG docker $USER

设置开机自启

systemctl enable docker

设置镜像

sudo mkdir -p /etc/docker

sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://docker.registry.cyou",
  "https://docker-cf.registry.cyou",
  "https://dockercf.jsdelivr.fyi",
  "https://docker.jsdelivr.fyi",
  "https://dockertest.jsdelivr.fyi",
  "https://mirror.aliyuncs.com",
  "https://dockerproxy.com",
  "https://mirror.baidubce.com",
  "https://docker.m.daocloud.io",
  "https://docker.nju.edu.cn",
  "https://docker.mirrors.sjtug.sjtu.edu.cn",
  "https://docker.mirrors.ustc.edu.cn",
  "https://mirror.iscas.ac.cn",
  "https://docker.rainbond.cc"]
}
EOF


sudo systemctl daemon-reload


sudo systemctl restart docker

查看docker镜像文件

docker images

查看docker进程

docker ps

安装MySQL

# 两个版本,安装自己需要的即可,本文安装的是8.0.40

docker pull mysql:8.0.40

docker pull mysql:5.7

启动mysql

docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123abc!@ -d mysql:8.0.40

参数解释:

  • --name 容器名称
  • -p 3306:3306 物理机端口:容器内部端口
  • -e 运行参数 初始化root账号密码
  • -d 后台运行 mysql8.0.40镜像名称加标签

查看mysql是否在启动进程

docker ps

在进程处可以看到 IMAGE 列有 mysql的话证明进程启动

在CONTATNER_ID列可以查看mysql的容器id,假设容器id为934e3c005153

进入mysql容器

docker exec -it 934e3c005153 /bin/bash

// 登录mysql
mysql -uroot -p123abc!@

修改密码

第一种

set password for root@localhost = password('123abc!@');

第二种用mysqladmin修改密码

1、打开cmd进入MySql的bin目录;(如我的路径是F:\MySQL\mysql-5.7.24-winx64\bin)

2、修改MySQL的root用户密码格式,mysqladmin -u用户名 -p旧密码;password 新密码

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root';
或
ALTER USER 'root'@'%' IDENTIFIED BY 'root';

退出mysql

exit;

退出docker

exit

查看进程

docker ps

关闭mysql容器

docker stop 934e3c005153

这是docker -ps已经无法查看mysql的容器id,该命令默认是查看运行的容器,但是可以通过 -a 查看全部容器

docker ps -a

启动mysql容器

docker start 934e3c005153 

测试连接

配置容器卷映射

启动容器时没有配置容器卷映射,当容器意外被删时,数据无法找回

启动 Mysql 容器,并配置容器卷映射:

docker run -d -p 3306:3306 \
           --privileged=true \
           -v /usr/local/mysql/log:/var/log/mysql \
           -v /usr/local/mysql/data:/var/lib/mysql \
           -v /usr/local/mysql/conf:/etc/mysql/conf.d \
           -e MYSQL_ROOT_PASSWORD=abc123 \
           --name mysql \
           mysql:5.7

-v 宿主机路径 容器内部路径

此时,即使mysql容器被删,执行一遍以上命令,还是可以恢复数据

因为启动时将容器做了容器卷映射,将mysql的配置(映射到/usr/local/mysql/conf)、数据(映射到/usr/local/mysql/data)、日志(映射到/usr/local/mysql/log)都映射到了宿主机实际目录,所以即使删除了容器,也不会产生太大影响。只需要再执行一下启动Mysql容器命令,容器卷还按相同位置进行映射,所有的数据便都可以正常恢复。

插入中文异常问题

某些版本的mysql插入中文时会异常,这是因为docker默认的字符集的问题,可以在mysql中使用以下命令查看数据库字符集:

show variables like 'character%';

返回的字符集中,character_set_databasecharacter_set_server等都为latin1字符集,所以会报错。

异常版:

正常版:

解决方法:

/usr/local/mysql/conf下新建 my.cnf,通过容器卷同步给mysql实例,解决中文乱码问题:

[client]
default_character_set=utf8
[mysqld]
collation_server = utf8_general_ci
character_set_server = utf8

重启mysql容器,使得容器重新加载配置文件:

docker restart mysql

设置开机自启

docker update --restart=always <container_name_or_id>

安装jdk

下载jdk

  • 方法1

www.oracle.com/java/techno…

jdk下载版本:jdk-8u291-linux-x64.tar.gz

在usr目录下新建一个文件夹bak

将下载好的jdk上传到 /usr/bak下

  • 方法2
wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" https://download.oracle.com/otn/java/jdk/8u291-b10/d7fc238d0cbf4b0dac67be84580cfb4b/jdk-8u291-linux-x64.tar.gz

解压jdk

tar -zxvf jdk-8u291-linux-x64.tar.gz

改名jdk解压文件名

mv jdk1.8.0_291 jdk1.8

移动jdk文件到 usr/local/目录

mv jdk1.8 /usr/local

进入usr/local目录

cd /usr/local

修改配置

修改配置文件

vim /etc/profile

添加配置

// 进入vim编辑器后,按a/i字母进入编辑模式,按esc是退出编辑模式,按:wq保存退出
// 到文件最后,空两三行插入下面内容

export JAVA_HOME=/usr/local/jdk1.8
export CLASSPATH=$:CLASSPATH:$JAVA_HOME/lib/
export PATH=$PATH:$JAVA_HOME/bin

查看配置是否生效

// 如果新增配置已经存在,证明编辑生效
cat /etc/profile

刷新配置

source /etc/profile

查看java是否生效

java -version

安装Nginx

下载

链接:nginx.org/en/download…

nginx下载版本:nginx-1.20.2.tar.gz

下载完后将其上传到服务器/usr/bak目录下

解压Nginx

1、安装nginx之前,需要安装相关依赖库

yum -y install gcc-c++ zlib-devel openssl-devel libtool

2、解压nginx安装包

tar -zxvf nginx-1.20.2.tar.gz

删除安装包

rm -rf nginx-1.20.2.tar.gz

3、配置和安装

cd nginx-1.20.2
./configure --prefix=/usr/local/nginx
make && make install

4、启动nginx

cd /usr/local/nginx/sbin
./nginx

5、查看nginx

ps -ef | grep nginx

6、重启nginx

./nginx -s reload

设置开机自启

创建nginx.service服务文件

vim /etc/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target

[Service]
Type=forking
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

重新加载服务

systemctl daemon-reload

加入开机自启

systemctl enable nginx

重启服务器测试

reboot

部署后端-JAVA

准备工作

网上clone下RuoYi-Vue的项目下来,准备部署,项目准备工作略过,完整指南查看官方部署指南,修改Redis与MySQL的相关配置,启动项目

打包部署

clearpackage

在服务器中,进入home目录,新建server目录,将包上传到此处

cd /homme

mkdir server

cd server

编写启动文件

touch start.sh

vim start.sh

start.sh 配置

#这里可替换为你自己的执行程序,其他代码无需更改

APP_NAME=(/home/server/ruoyi-admin.jar)
#使用说明,用来提示输入参数
usage() {
    echo "Usage: sh robotcenter.sh [start|stop|restart|status]"
    exit 1
}

#检查程序是否在运行
is_exist(){
  pid=`ps -ef|grep $1|grep -v grep|awk '{print $2}'`
  #如果不存在返回1,存在返回0     
  if [ -z "${pid}" ]; then
   return 1
  else
    return 0
  fi
}

#启动方法
start(){
  for i in ${APP_NAME[@]}
  do
    is_exist $i
	if [ $? -eq 0 ]; then
	  echo "${i} is already running. pid=${pid}"
	else
	  nohup java -jar $i  >${i}.log 2>&1 &
	fi
  done
}

#停止方法
stop(){
  for i in ${APP_NAME[@]}
  do
    is_exist $i
    if [ $? -eq 0 ]; then
      kill -9 $pid
    else
      echo "${i} is not running"
    fi  
  done
}

#输出运行状态
status(){
  for i in ${APP_NAME[@]}
  do
    is_exist $i
    if [ $? -eq 0 ]; then
      echo "${i} is running. Pid is ${pid}"
    else
      echo "${i} is NOT running."
    fi
  done
}

#重启
restart(){
  stop
  sleep 5
  start
}

#根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
  "start")
    start
    ;;
  "stop")
    stop
    ;;
  "status")
    status
    ;;
  "restart")
    restart
    ;;
  *)
    usage
    ;;
esac

授权

chmod 777 start.sh 

启动

./start.sh start

暂停

./start.sh stop

重启

./start.sh restart

查看日志

tail -f ruoyi-admin.jar

开放安全组或防火墙

接口测试

部署前端

准备工作

安装依赖,

# 安装依赖
npm install --registry=https://registry.npmmirror.com

修改vue.config.js的proxy代理配置

proxy: {
  [process.env.VUE_APP_BASE_API]: {
    target: `http://193.112.187.168:8080`,// 修改成代理端口
    changeOrigin: true,
    pathRewrite: {
      ['^' + process.env.VUE_APP_BASE_API]: ''
    }
  }
},

并启动项目

打包部署

前端部署是会存在多个项目的情况,为了能管理好前端项目,修改下打包相关的配置

  • 修改vue.config.js下的publicPath
publicPath: "/manage/",
  • 修改目录router->index.js
export default new Router({
  mode: 'history',
  base: 'manage', // 新增配置
  scrollBehavior: () => ({ y: 0 }),
  routes: constantRoutes
})
  • 修改相关的重定向路由,搜索全局location.href = '/index',替换成location.href = '/manage/index'

执行打包命令

npm run build:prod

可以发现,执行打包时,加多了prod命令,其实这是一个环境变量的指令

prod使用的是.env.production里的环境变量,里面VUE_APP_BASE_API这个环境变量是在我们的请求封装里使用了,这里可以先忽略继续往下走

进入nginx目录下的html目录,创建manage文件夹,上传前端包

配置nginx.conf文件

cd /usr/local/nginx/conf

vim nginx.conf

加入以下内容

location /manage {
    alias   html/manage;
    try_files $uri $uri/ /manage/index.html;
    index  index.html index.htm;
}

重启Nginx

cd /usr/local/nginx/sbin

./nginx -s reload

访问网页,注意这里访问时需要加多个manage

可以看到访问正常,但接口提示失败了,仔细看接口路径,是不是多了前面的环境变量/prod-api

这是干什么用的呢?为什么需要这个特殊的标识呢?去掉这个标识,写上接口端口号不就是能正常访问的接口吗?

测试一下

确实将/prod-api改成:8080接口就正常,那为什么不这么做呢?

原来,全部所有的生产开发都一样,不直接把接口地址在前端写死,试想一下,如果把接口写死,如果某天服务器要换了,接口全部都要重新部署到新的服务器,前端是不是要重新打包?明明前端没改业务逻辑,仅仅是接口地址变了,为什么要做这种无用功呢?

除此之外,我们前面是不是还需要单独的去为服务器开放8080的安全组/防火墙,在很多时候,端口开放的越多也是一种风险

为了解决以上的问题,人们就想到了好的办法,使用Nginx的代理转发

将一下配置添加在nginx.conf文件中

location /prod-api/ {
    charset utf-8;
    proxy_connect_timeout 30s;
    proxy_send_timeout 30s;
    proxy_read_timeout 30s;           
    proxy_set_header Forwarded host=$host:$server_port;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://xxx:8080/;
}

修改完配置,记得重启

./nginx -s reload

此时就正常啦

最后别忘记,服务器上的安全组/防火墙记得删除

部署Nodejs项目-Haschat

准备工作

获取项目

前端:gitee.com/howcode/has… 后端:gitee.com/howcode/has…

分别clone项目下来,并且输入npm install安装依赖

在数据库中创建haschat数据库,并且在has-chat-service目录中的store目录下,导入相关的表

image.png

导入成功后,修改has-chat-service->config.js的数据库配置文件以及邮箱配置(用于发送用户注册验证码)

image.png

运行后端

npm run start

image.png

如果有提示:Client does not support authentication protocol requested by server; consider upgrading MySQL client

是因为:最新的MySQL模块并未完全支持MySQL 8.0的caching_sha2_password加密方式,而MySQL 8.0中默认仍然是caching_sha2_password加密方式,因此用户认证不通过了。

解决:


# 进入mysql容器
docker exec -it mysql /bin/bash

# 连接mysql
mysql -uroot -p

# 修改规则与密码
alter user 'root'@'%' identified by '新密码';

alter user 'root'@'%' identified with mysql_native_password by '新密码';

# 刷新权限
FLUSH PRIVILEGES; 

重新启动项目即可

顺便启动前端项目,验证

npm run dev

如果到这步都没问题,就可以准备部署了

部署前准备

既然是部署后端nodejs服务,那就需要安装nodejs,但是了解前端的都知道,nodejs版本特别多,而且每个版本兼容性特别差,因此需要管理工具 nvm

安装nvm

浏览器输入一下地址,并保存install.sh文件(由于是github的文件,可能需要梯子)

https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh

将install.sh文件上传到服务器

授权执行

chmod +x install.sh

执行安装

./install.sh

查看环境配置

cd /root

cat .bashrc

重载环境变量

source /root/.bashrc

查看版本

nvm --version

安装nodejs

查看有哪些版本可安装

nvm ls-remote

安装 16.17.0 版本的nodejs

# 安装
nvm install v14.21.1

# 查看node版本
node --version

# 查看npm版本
npm --version

设置阿里镜像cnpm

npm install -g cnpm --registry=https://registry.npmmirror.com

安装npm管理工具 nrm,以便可以随时在淘宝源和官方源切换

cnpm install -g nrm

切换淘宝源

nrm use taobao

安装pnpm

cnpm i -g pnpm

安装pm2

cnpm i -g pm2

查看版本

pm2 -v

部署工作

部署后端

将后端项目上传到服务器中

image.png

切换nodejs版本为v16.7.0

nvm use 16.7.0

安装依赖

npm install

启动项目试试

npm run start

image.png

ctrl+c关闭项目,使用pm2启动项目

pm2 start npm --name haschat-api -- run start

查看日志

pm2 logs

查看全部服务

pm2 list

设置自动重启

pm2 save

pm2 startup

停止服务

pm2 delete nest-blog

部署前端

由于我服务器存在多个前端项目,所以需要加个前端二级目录,添加haschat标识

image.png

image.png

.env.production环境变量修改成你服务器的地址

image.png

执行打包

npm run build:prod

上传前端包

image.png

修改nginx.conf配置

location /haschat {
  alias html/haschat;
  try_files $uri $uri/ /haschat/index.html;
  index index.html index.htm;
}


location /api/ {
  charset utf-8;
  proxy_connect_timeout 30s;
  proxy_send_timeout 30s;
  proxy_read_timeout 30s;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_pass http://xxxx:9527/api/;
}

location ^~ /socket.io/ {
  proxy_pass http://xxxx:9527/socket.io/;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
}

重启nginx

./nginx -s reload

image.png

最后

本次部署流程,是我直接重置服务器后(相当于一台新服务器)从零到一、完完整整的操作流程步骤,加上一边写文档记录,整整历时两天完成的,原本的服务器是windows系统,也为了给小白学会部署出了一期的部署教程:从选购服务器到部署

有人问:为什么要折腾?为什么要出这样的教程?网上一搜不是一堆吗?

确实如此,但是网上的教程特别零碎,想要如此完整流程的,几乎没有,我也是从小白走过来,知道这种过程的不易,所以想了想,如果能帮助到新手的话,这也是一件很酷的事,于是就做了

如果你对技术/行业交流有兴趣,欢迎添加howcoder微信,邀你进群交流