部署MySQL

安装

注意:

  • 端口号问题
  • 如果很慢,建议配置镜像加速器
1
2
3
4
5
6
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
mysql

镜像和容器

当我们利用Docker安装应用时,Docker会自动搜索并下载应用镜像(image)。镜像不仅包含应用本身,还包含应用运行所需要的环境、配置、系统函数库。Docker会在运行镜像时创建一个隔离环境,称为容器(container)

命令解读

  • docker run:创建并运行一个容器,-d是让容器在后台运行
  • –name mysql:给容器起个名字,必须唯一
  • -p 3306:3306:设置端口映射
  • -e KEY=VALUE:是设置环境变量
  • mysql:指定运行的镜像的名字
  • –network 指定网桥

镜像命名规范

  • 镜像名称一般分两部分组成:[repository]:[tag]
    • 其中repository就是镜像名
    • tag是镜像的版本
  • 在没有指定tag时,默认是latest,代表最新版本的镜像

Docker基础

常见命令

更多命令请查看官方文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#以Nginx为例
# 第1步,去DockerHub查看nginx镜像仓库及相关信息

# 第2步,拉取Nginx镜像
docker pull nginx

# 第3步,查看镜像
docker images
# 结果如下:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 16 months ago 141MB
mysql latest 3218b38490ce 17 months ago 516MB

# 第4步,创建并允许Nginx容器
docker run -d --name nginx -p 80:80 nginx

# 第5步,查看运行中容器
docker ps
# 也可以加格式化方式访问,格式会更加清爽
docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"

# 第6步,访问网页,地址:http://虚拟机地址

# 第7步,停止容器
docker stop nginx

# 第8步,查看所有容器
docker ps -a --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"

# 第9步,再次启动nginx容器
docker start nginx

# 第10步,再次查看容器
docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"

# 第11步,查看容器详细信息
docker inspect nginx

# 第12步,进入容器,查看容器内目录(添加可输入的终端)
docker exec -it nginx bash
# 或者,可以进入MySQL
docker exec -it mysql mysql -uroot -p

# 第13步,删除容器
docker rm nginx
# 发现无法删除,因为容器运行中,强制删除容器
docker rm -f nginx

# 保存
docker save -o nginx.tar nginx:latest

命令别名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 修改/root/.bashrc文件
vi /root/.bashrc
内容如下:
# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias dps='docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"'
alias dis='docker images'

# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi

# 使别名生效
source /root/.bashrc

数据卷

引出:镜像中只包含必要的,像vi编辑器几乎所有的镜像都不包含,那么应该如何修改呢?举个例子,如果是nginx,当你想要部署静态资源目录或者想修改index.html文件时,那就必然要用到相关命令,但在容器中是没有vi等相关命令的

数据卷(volume)是一个虚拟目录,是容器内目录宿主机目录之间映射的桥梁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 帮助
docker volume --help

# 创建数据卷
docker volume create

# 查看所有数据卷
docker volume ls

# 删除指定数据卷
docker volume rm

# 查看某个数据卷的详情
docker volume inspect

# 清除数据卷
docker volume prune
  • 在执行docker run命令时,使用-v数据卷:容器内目录可以完成数据卷挂载
  • 当创建容器时,如果挂载了数据卷且数据卷不存在,会自动创建数据卷

本地目录挂载

1
docker inspect [容器名]
  • 在执行docker run命令时,使用-v本地目录:容器内目录 可以完成本地目录挂载
  • 本地目录必须以“/”或”./“开头,如果直接以名称开头,会被识别为数据卷而非本地目录
    • -v mysql:/var/lib/mysql 会被识别为一个数据卷叫mysql
    • -v./mysql:/var/lib/mysql 会被识别为当前目录下的mysql目录

自定义镜像

镜像就是包含了应用程序、程序运行的系统函数库、运行配置等文件的文件包。构建镜像的过程其实就是把上述文件打包的过程

构建一个Java镜像的步骤:

  • 准备一个Linux运行环境
  • 安装JRE并配置环境变量
  • 拷贝Jar包
  • 编写运行脚本

Dockerfile

Dockerfile就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。将来Docker可以根据Dockerfile帮我们构建镜像。常见指令如下:

我们可以基于Ubuntu基础镜像,利用Dockerfile描述镜像结构,也可以直接基于JDK为基础镜像(Java),省略前面的步骤

当编写好了Dockerfile,可以利用下面命令来构建镜像:

1
docker build -t myImage:1.0 .
  • -t :是给镜像起名,格式依然是repository:tag的格式,不指定tag时,默认为latest
  • . :是指定Dockerfile所在目录,如果就在当前目录则指定为”.”

网络

默认情况下,所有容器都是以bridge方式连接到Docker的一个虚拟网桥上

加入自定义网络的容器才可以通过容器名互相访问,Docker的网络操作命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 创建一个网络
docker network create

# 查看所有网络
docker network ls

# 删除指定网络
docker network rm

# 清除未使用的网络
docker network prune

# 使指定容器连接加入某网络
docker network connect

# 使指定容器连接离开某网络
docker network disconnect

# 查看网络详细信息
docker network inspect

项目部署

部署Golang服务

安装MySQL

拉取镜像

1
docker pull mysql

创建容器并启动(按需修改参数,相关解释在上文皆有提到)

1
2
3
4
5
6
7
8
9
10
11
docker run \
--name mysql \
-p 3306:3306 \
--restart=always \
-e TZ=Asia/Shanghai \
-v /data/mysql/conf:/etc/mysql/conf.d \
-v /data/mysql/data:/var/lib/mysql \
-v /data/mysql/log:/var/log/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-d \
mysql

安装Redis

拉取镜像

1
docker pull redis

准备配置文件

1
2
3
4
5
6
#配置文件
mkdir /data/redis/conf
#数据存储
mkdir /data/redis/data
#mysql日志
mkdir /data/redis/log

修改配置文件

先去官网寻找自己版本的redis.conf => Redis configuration | Docs

1
2
3
4
5
6
7
8
9
10
11
# 新建 redis.conf 文件
touch /data/redis/conf/redis.conf
# 使用vim进行编辑
vim /data/redis/conf/redis.conf
# 取消本地绑定,允许redis外地连接
注释掉 # bind 127.0.0.1
# 取消requirepass注释,并将foobared修改为自己的密码(如果不想设置密码又想被外部宿主机访问,那就需要另外定位到protected-mode yes,将参数修改为no)
# 默认 no,表示不以守护进程启动,因为docker run -d本身就是后台启动
daemonize no
# 开启持久化,根据需求选择是否开启
appendonly yes

创建容器并启动

1
2
3
4
5
6
7
8
9
10
docker run \
--name redis \
-p 6379:6379 \
--restart=always \
-v /data/redis/conf:/usr/local/etc/redis \
-v /data/redis/log:/var/log/redis.log
-v /data/redis/data:/data \
-d \
redis \
redis-server /usr/local/etc/redis/redis.conf

将程序打包成镜像

打包

1
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GIN_MODE=release go build -o example
  • GOOS=linux:指定目标操作系统为 Linux。
  • GOARCH=amd64:指定目标架构为 64 位。
  • CGO_ENABLED=0:禁用 CGO 以确保生成静态链接的二进制文件。
  • -o example:输出的二进制文件名称。

在这个文件夹下创建一个dockerfile(scratch为空镜像,不用自己创建)

1
2
3
4
5
6
FROM scratch
LABEL maintainer="设置镜像维护者信息"
WORKDIR /app
COPY example /app
EXPOSE 8080
ENTRYPOINT ["./app/example"]

构建镜像

1
docker build -t example .

查看是否存在

1
docker images

运行

修改config.yaml中mysql和redis的配置,本文提供两种方法。

  • 第一种可以直接替换localhost,换成docker分配的IPAddress即可,使用该命令进行查看docker inspect <container_id> | grep IPAddress
  • 第二种就是自己建立自定义网络,具体命令可在上文查看,将对应的host改为mysql容器名字和redis容器名字即可
1
2
3
4
5
6
7
8
docker run \
--privileged=true \
--restart=always \
--name example \
-p 8080:8080 \
-v /example/config.yaml:/app/config.yaml
-d \
example

实时查看日志

1
docker logs -f <container_name>

DockerCompose

Docker Compose通过一个单独的docker-compose.yml模板文件(YAML格式)来定义一组相关联的应用容器,帮助我们实现多个相互关联的Docker容器的快速部署

以下提供一个示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
version: "3.8"

services:
mysql:
image: mysql
container_name: mysql
ports:
- "3306:3306"
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123
volumes:
- "./mysql/conf:/etc/mysql/conf.d"
- "./mysql/data:/var/lib/mysql"
- "./mysql/init:/docker-entrypoint-initdb.d"
networks:
- hm-net
hmall:
build:
context: .
dockerfile: Dockerfile
container_name: hmall
ports:
- "8080:8080"
networks:
- hm-net
depends_on:
- mysql
nginx:
image: nginx
container_name: nginx
ports:
- "18080:18080"
- "18081:18081"
volumes:
- "./nginx/nginx.conf:/etc/nginx/nginx.conf"
- "./nginx/html:/usr/share/nginx/html"
depends_on:
- hmall
networks:
- hm-net
networks:
hm-net:
name: hmall

基础语法

1
docker compose [OPTIONS] [COMMAND]
类型 参数或指令 说明
Options -f 指定compose文件的路径和名称
-p 指定project名称。project就是当前compose文件中设置的多个service的集合,是逻辑概念
Commands up 创建并启动所有service容器
down 停止并移除所有容器、网络
ps 列出所有启动的容器
logs 查看指定容器的日志
stop 停止容器
start 启动容器
restart 重启容器
top 查看运行的进程
exec 在指定的运行中容器中执行命令

OPTIONS记得加一下-d(以后台的方式运行)

附:Ubuntu 部署 Gin+Vue 前后端分离项目

声明

下文转载惜寞部长相关博客,并进行整合

MySQL

安装MySQL

更新软件包列表

1
sudo apt update

查看是否安装MySQL

1
dpkg -l | grep mysql

安装MySQL

1
sudo apt install mysql-server

查看是否安装

1
mysql --version

查看 MySQL 状态

1
sudo systemctl status mysql

相关命令

1
2
3
4
5
6
# 启动
sudo systemctl start mysql
# 停止
sudo systemctl stop mysql
# 重启
sudo systemctl restart mysql

开机自启动(可选)

注:使用systemd管理服务,前提是使用 apt 安装的 MySQL

当前新版本的 MySQL 服务默认是开机自启动,可以通过前面的sudo systemctl status mysql命令查看

enabled表示当前 MySQL 服务是开机自启动

可以用下面命令关闭开机自启动

1
sudo systemctl disable mysql

也可以重新开启

1
sudo systemctl enabled mysql

MySQL 安全配置向导

MySQL 安装文件时会附带一个名为mysql_secure_installation的脚本,我们可以通过运行该脚本提高 MySQL 的安全性

1
sudo mysql_secure_installation

这里有一个插件VALIDATE PASSWORD PLUGIN,它可以测试 MySQL 用户密码的强度,并且提高安全性,如果你想设置验证密码插件,按y回车后移动到下一个步骤
注:如果不想设置复杂密码(比如想设置密码是 123456)的建议选择输入n不设置验证密码的插件,因为即使是下面的 LOW 策略也要求密码长度至少为8位(安全性哪有方便重要

这里给出了低级,中级,高级三个级别的密码验证策略

  • 低级 长度 >= 8
  • 中级 在低级的基础上,需要同时包含数字,大小写字母和特殊字符
  • 高级 在中级的基础上,要求密码不能存在字典文件中

可以输入对应级别前的数字进行选择

默认情况下,使用 auth_socket 进行身份验证,因此跳过为 root 用户设置密码。

如果你想改用密码身份验证,可以使用”ALTER_USER”命令进行设置。
请参考 https://dev.mysql.com/doc/refman/8.0/en/alter-user.html#alter-user-password-management 获取更多信息。

这边仅做一个补充,为 root 用户设置密码的操作在第三部分会提到

询问是否删除匿名用户,建议输入y删除

  • 在 MySQL 中,默认情况下会存在一个匿名用户(没有用户名和密码就可以登录),该用户具有一些基本的权限
  • 如果每个用户都有明确的身份和权限,可以更容易地追踪和监视数据库的活动,识别潜在的安全问题
  • 为了确保数据库仅允许经过授权的用户进行访问和操作,减少潜在的安全风险,建议删除匿名用户

询问是否禁止 root 远程登录,根据自己需求选择,如果你想要使用 root 用户远程连接 MySQL 数据库,可以输入任意键跳过该设置
出于安全考虑,建议输入y禁止

  • root 是 MySQL 数据库的超级管理员,拥有最高权限,一旦泄露后果非常严重,禁止 root 用户远程登录可以降低潜在的风险
  • 更推荐的做法是创建一个普通用户,并为其授予适当的权限,以便远程访问数据库,这样做可以限制对数据库的访问权限,并提供额外的安全层
  • 禁止 root 用户远程登录还可以防止意外的操作或误操作

询问是否删除 test 数据库,输入y删除

询问是否重新加载权限表,输入y重新加载

修改 root 用户验证方式(可选)

在 MySQL 5.7(及更高版本)的 Ubuntu 系统中,root 用户默认使用 auth_socket 插件授权,而不是通过密码进行身份验证(即使输入了密码也不会验证),但这并不意味着安全性降低,因为他有两个限制:

  • 只能用 UNIX 的 socket 方式登陆,这就保证了只能本地登陆,用户在使用这种登陆方式时已经通过了操作系统的安全验证
  • 操作系统的用户和 MySQL 数据库的用户名必须一致,如果你要登陆 MySQL 的 root 用户,必须使用操作系统的 root 用户

在多数情况下,这可以获得更高的安全性和可用性,但也会阻碍你使用外部程序(如 phpMyAdmin)访问数据库,或者是想使用 root 用户远程连接数据库等
对此有两种解决方案:

  • 将身份验证方式从 auth_socket 修改为 caching_sha2_password(即使用密码验证 root 用户)
    • 从网上教程一般是修改为 mysql_native_password,主要原因是因为 caching_sha2_password 在 MySQL 8.0.3 才开始引入,并且由老版本升级为新版本时会出现一些问题
    • 但相比于 mysql_native_password,caching_sha2_password 的安全性更高,从 MySQL 8.0.4 开始,此插件成为 MySQL 服务器的新默认身份验证插件
    • 因为我们安装的是新版的 MySQL,所以我更建议使用 caching_sha2_password
  • 创建一个新的管理用户,拥有所有数据库的访问权限

使用root身份登录MySQL

1
sudo mysql

查看不同用户使用的身份验证方法

1
SELECT user,authentication_string,plugin,host FROM mysql.user;

可以看到 root 用户确实是使用的 auth_socket 插件进行身份验证,并且密码为空

方案一:修改身份验证方式

输入下面命令将 root 用户的身份验证方式 auth_socket 修改成 caching_sha2_password,并设置登录的密码(包含在单引号之间)
注:需要满足在安全配置向导中选择的密码强度

1
ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'your_password';

输入下面命令,重新加载授权表并将更改更新到 MySQL 数据库

1
FLUSH PRIVILEGES;

完成后,再次运行以下命令确认 root 用户不再使用 auth_socket 进行身份验证

1
SELECT user,authentication_string,plugin,host FROM mysql.user;

输入exit退出MySQL

由于我们更改了 root 的身份验证方法,因此我们不能再使用之前的命令(即sudo mysql)登录 MySQL

我们在登陆时需要加上用户名和密码参数

1
mysql -u root -p

方案二:创建新的管理用户(推荐)

创建一个新的管理用户,并赋予所有数据库的访问权限
注:需要满足在安全配置向导中选择的密码强度

1
2
3
4
# 创建用户并设置密码
CREATE USER 'new_root'@'localhost' IDENTIFIED BY 'your_password';
# 赋予用户所有权限
GRANT ALL PRIVILEGES ON *.* TO 'new_root'@'localhost' WITH GRANT OPTION;

输入下面命令,重新加载授权表并将更改更新到 MySQL 数据库

1
FLUSH PRIVILEGES;

查看创建用户的权限

1
show grants for new_root@localhost;

可以看到所有权限都被赋予了我们新创建的 new_root 用户,之后我们就能将该用户当作 root 用户使用

配置远程连接

先使用 root 身份登录 MySQL

1
2
3
4
# 没修改过 root 用户身份验证方式
sudo mysql
# 修改过 root 用户身份验证方式
mysql -u root -p
  • 推荐的做法是创建一个普通用户,并为其授予适当的权限,用来远程访问数据库
  • 该部分可以参考本文 修改 root 用户验证方式(可选) 中的 方案二:创建新的管理用户 部分
  • 不同的地方在于可以根据自己的实际情况赋予创建的用户权限,相关命令可以自行百度,懒得写了
  • 如果暂时不清楚需要给什么权限,可以先赋予所有权限(跟着方案二即可),后续再修改
  • 如果想要使用 root 用户进行远程连接,请先确保已经跟着方案一修改好了 root 用户的验证方式
  • root 用户或者是自己新创建的用户,后续配置远程连接的操作都是一样的,这里用 root 用户进行演示,如果选择创建一个新的用户进行远程连接,将带有 root 用户名的部分都替换成新创建用户的用户名即可

查看 root 用户的 host

1
SELECT user,host FROM mysql.user;

如果 root 用户的 host 为localhost,表示只能在本地(该服务器内)登录 root 用户
修改 root 用户的 host 为%
注:host 为%表示所有 ip 都有连接权限

1
2
3
4
5
6
# 使用名为 mysql 的数据库
use mysql
# 修改 host
update user set host = '%' where user = 'root';
# 刷新权限
flush privileges;

再次查看 root 用户的 host,确认已经修改为%

输入exit退出 MySQL,回到 Ubuntu 终端
使用 vim 查看编辑 MySQL 配置文件,输入下面命令后回车

1
vim /etc/mysql/mysql.conf.d/mysqld.cnf

将该行(意思是只允许本地访问) bind-address

注释掉(在前面加#
然后按下Esc键退出编辑模式
再输入:wq(包括:号,在英文输入法下)后回车即保存退出

重启 mysql 服务

1
sudo systemctl restart mysql

云服务器放行 3306 端口

在云服务器厂商找到对应云服务器的防火墙,并放行 3306 端口(MySQL 的默认端口)

Redis

安装 Redis

更新软件包列表

1
sudo apt update

查看是否安装 Redis

1
dpkg -l | grep redis

安装 Redis

1
sudo apt install redis-server

查看版本

1
redis-server -v

查看 Redis 状态

一旦安装完成,Redis 服务将会自动启动,想要查看 Redis 服务运行状态可以输入下面命令查看

1
sudo systemctl status redis

启动、重启、停止 Redis 服务的命令

1
2
3
4
5
6
# 启动
sudo systemctl start redis
# 停止
sudo systemctl stop redis
# 重启
sudo systemctl restart redis

测试 Redis

1
redis-cli

输入ping,返回pong说明成功!

1
exit

配置 Redis 远程连接

配置 Redis 主要是对配置文件 redis.conf 进行修改,默认位置在 /etc/redis/redis.conf

查找Redis配置文件

使用之前的sudo systemctl status redis命令查看 Redis 服务的状态,输出内容中有配置文件的位置

1
cat /lib/systemd/system/redis-server.service

编辑配置文件

1
vim /etc/redis/redis.conf

Redis 默认开启保护模式,并且绑定了本地,也就是只有云服务器本地才能连接并操作 Redis

  • 保护模式:如果符合下面两个条件(不是之一)则无法被远程连接
  1. 没有明确使用 bind 绑定某个 ip 地址
  2. 没有设置密码
  • 想要实现远程连接主要有三种方案
  1. 取消本地绑定(可以被任何 ip 访问),设置密码
  2. 明确绑定某个 ip 地址,设置密码(可选)
  3. 取消本地绑定(可以被任何 ip 访问),关闭保护模式

取消本地绑定/绑定某个 ip 地址

移动光标定位到bind 127.0.0.1 ::1

输入i进入编辑模式(在英文输入法下)
bind 127.0.0.1 ::1的意思是只接受本机的访问请求

  • 如果想取消本地绑定(可以被任何 ip 访问)
    • 将该行注释掉(在前面加#,即# bind 127.0.0.1 ::1),表示接受任何 ip 地址的访问
  • 如果想明确绑定某个 ip 地址
    • 127.0.0.1替换为指定的 ip 地址即可

设置密码

移动光标定位到# requirepass foobared

取消该行注释(删除#),并将foobared修改为你想要设置的密码

配置修改生效后再进入 Redis 命令行时需要输入密码登录
即使用redis-cli -a your_password命令登录,your_password是你自己设置的密码

如果不输入密码进入则会报错未授权

关闭保护模式

移动光标定位到protected-mode yes

yes修改为no即表示关闭保护模式

总结

  • 一般在上线部署时(只在云服务器本地运行),不需要修改配置文件
  • 线下调试时,希望开发环境也可以连接到 Redis(方案一)
    • # bind 127.0.0.1 ::1,取消本地绑定(可以被任何 ip 访问)
    • protected-mode yes,保护模式默认开启即可
    • requirepass your_password,设置密码

以上仅作为参考,具体可以自行选择

重启Redis服务

Esc退出编辑模式,然后输入:wq后回车保存文件并退出(在英文输入法下)
输入下面命令重启 Redis 服务以应用修改后的配置文件

1
sudo systemctl restart redis

输入以下命令查看 Redis 服务所监听的 ip 和端口(以方案一设置为例)

1
netstat -tlpn | grep redis

可以看到 Redis 绑定的 ip 已经变成了 0.0.0.0,即接受任何 ip 地址的访问

云服务器放行 6379 端口

在云服务器厂商找到对应云服务器的防火墙,并放行 6379 端口(Redis 的默认端口)

后端(GoLand)

部署

Go 项目打包

Go 支持跨平台编译,因此我们可以很轻松的将当前平台的 Go 项目打包成能够在 Linux 运行的文件
进入到 main.go 的文件目录下,执行以下命令(打包前记得将环境或者配置修改为服务器的)

Windows 系统下
1
2
3
4
SET CGO_ENABLE=0
SET GOOS=linux
SET GOARCH=amd64
go build main.go

注:在 cmd 中执行,PowerShell 中不知道为什么不起作用(编译出来还是 Windows 下的 .exe 文件)

参数说明:

  • CGO_ENABLE 是否开启 CGO,默认为 1 开启 CGO(不支持交叉编译),0 表示关闭
  • GOARCH 表示目标平台的体系架构
  • GOOS 表示目标平台的操作系统 Linux、Windows、Darwin(Mac)
Mac 系统下
1
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
Linux 系统下
1
go build main.go

等待编译完成后就可以得到一个不带后缀的二进制文件,默认名为main
如果想要指定输出的文件名,可以在 go build 时加上 -o 参数,如

1
go build -o cms main.go

将打包文件上传到服务器

可以使用 xftp 上传打包文件至服务器,也可以使用对应云服务器厂商自带的 WebShell
这边将打包好的 cms 文件上传到/opt/go/cms文件夹下(文件路径可以自己选择)
注:如果有配置文件也需要一起上传

修改文件权限

cd /opt/go/cms通过ls -l命令查看

想要运行该文件,我们至少需要拥有执行该文件的权利,执行下面的命令

1
chmod 740 cms

这时候我们其实已经可以运行了,输入./cms去运行我们编译好的文件

没有报错说明已经启动成功了
没有别的信息显示是因为部署在正式环境中,设置了gin.SetMode(gin.ReleaseMode)(Gin 的生产环境模式)(在程序的main函数中)

云服务器放行端口

想要访问后端服务,需要将服务对应运行的端口(比如我这边就是默认跑在8080端口)放开,不然在外部是访问不到服务器上的后端服务的
在云服务器厂商找到对应云服务器的防火墙,并放行 8080 端口(对应你自己后端服务的运行端口)

使用 Systemd 守护进程

现在我们希望我们的后端服务能在后台运行,并且不会随着我们终端的关闭而退出,这里就需要用到守护进程,守护进程是一个在后台运行并且不受任何终端控制的进程,这里我们选择使用 systemd 守护进程
注:本文不详细讲解 systemd,建议自行查阅相关知识

创建service文件

CTRL+C结束启动的服务回到 linux 命令行
/etc/systemd/system路径下新建一个cms.service文件,文件名可以自己取,文件后缀.service

1
touch /etc/systemd/system/cms.service
编辑 service 文件
1
vim /etc/systemd/system/cms.service

输入i进入编辑模式(在英文输入法下)

1
2
3
4
5
6
7
8
9
10
11
12
[Unit]
Description=cms(contact manager system)backend server daemon

[Service]
Type=simple
ExecStart=/opt/go/cms/cms
WorkingDirectory=/opt/go/cms
Restart=always
RestartSec=10s

[Install]
WantedBy=multi-user.target

参数解释(想要了解更多参数和配置可以参考这篇 利用 Systemd 守护进程 | 派大星的石头屋

  • Unit
    • Description:简短描述
  • Service
    • Type:启动类型,simple表示ExecStart字段启动的进程为主进程
    • ExecStart:启动当前服务的命令,即打包文件的具体路径
    • WorkingDirectory:指定服务运行目录,即打包文件所在的文件夹
    • Restart:定义何种情况 Systemd 会自动重启当前服务,always表示总是重启
    • RestartSec:自动重启当前服务间隔的秒数
  • Install
    • WantedBy:它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入/etc/systemd/system目录下面以 Target 名 + .wants后缀构成的子目录中

DescriptionExecStartWorkingDirectory修改为自己的即可
然后将修改完的代码粘贴到我们正在编辑的文件中

Esc退出编辑模式,输入:wq(包括:,在英文输入法下)后回车即保存退出

启动service

输入下面命令即可启动后端服务

1
sudo systemctl start cms # cms 对应修改为你之前创建的 service 文件名

然后可以通过下面命令查看服务状态

1
sudo systemctl status cms # cms 对应修改为你之前创建的 service 文件名

active (running)说明服务已经成功启动,即我们的后端服务已经在后台运行了

附上其他相关命令

1
2
3
4
5
6
7
8
# 停止
sudo systemctl stop cms # cms 对应修改为你之前创建的 service 文件名
# 重启
sudo systemctl restart cms # cms 对应修改为你之前创建的 service 文件名
# 设置开机自启动
sudo systemctl enable cms # cms 对应修改为你之前创建的 service 文件名
# 取消开机自启动
sudo systemctl disable cms # cms 对应修改为你之前创建的 service 文件名

Nginx 反向代理,将域名映射到 ip:port

完成部署后后端服务已经可以通过服务器的 ip 地址和端口进行访问
如果想实现将某个域名映射到 ip:port,即通过访问域名实现对后端服务的访问,我们需要用 Nginx 进行一个反代(因为域名只能绑定 ip)
注:本文不详细讲解 Nginx,建议自行查阅相关知识

安装 Nginx

1
sudo apt install nginx

可以输入下面命令查看 Nginx 服务状态

1
sudo systemctl status nginx

安装完成后,Nginx 服务会自己启动,可以看到 Nginx 服务已经正常运行

配置文件部分说明

Nginx 配置文件路径默认在/etc/nginx
可以输入下面命令查看 Nginx 配置文件位置

1
nginx -t

cd /etc/nginx到 Nginx 目录下,ls查看结构

  • nginx.conf 即 Nginx 的主要配置文件,可以直接在该文件中进行修改(大多数教程也是这么做的),但是如果以后部署的服务多起来,都放在一个配置文件中会显得混乱和臃肿
  • 新版本的 Nginx 允许我们在 nginx.conf 中导入其他文件夹中的 .conf 文件,因此我们可以针对不同的服务,建立不同的 conf 配置文件,方便管理
  • 而 Nginx 已经为我们建好了一个文件夹,并且导入到了配置文件中,即 conf.d 文件夹,我们可以直接在该文件夹下新建和添加配置文件
  • 注:nginx.conf 中有关于 Nginx 整体的相关配置,但这里不多介绍,我们也不去修改
新建配置文件

/etc/nginx/conf.d路径下新建一个cms.conf文件,文件名可以自己取,文件后缀.conf

1
touch /etc/nginx/conf.d/cms.conf
编辑配置文件
1
vim /etc/nginx/conf.d/cms.conf
1
2
3
4
5
6
7
8
9
10
server {
listen 80;
# 服务端绑定的域名
server_name cms-back.ximo210.top;

location / {
# 需要映射到的端口
proxy_pass http://localhost:8080;
}
}
  • server_name填入你要绑定的域名
  • proxy_pass填入你需要映射到的端口,比如我需要的是 8080 端口
  • listen 80表示的是监听的端口,因为 http 请求默认访问的是 80 端口,举例来说当我们在访问www.baidu.com的时候其实访问的是www.baidu.com:80,不过 80 可以省略

将上面的代码理解一下就是当我直接访问域名时,Nginx 会监听到 80 端口有请求,然后做一个反向代理将这个请求发送到 8080 端口,实现将对域名的请求映射到 ip:port
将修改完的代码粘贴进配置文件

Esc退出编辑模式,输入:wq(包括:,在英文输入法下)后回车即保存退出

重启 Nginx

输入下面命令重启 Nginx 以应用修改后的配置文件

1
sudo nginx -s reload

配置 SSL 证书

跟博客配置类似,本文不再赘述

这里附上配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
server {
listen 80;
# 服务端绑定的域名
server_name cms-back.ximo210.top;
# 强制跳转https
rewrite ^/(.*) https://$server_name$request_uri? permanent;
}

server {
# SSL 默认访问端口号为 443
listen 443 ssl;
# 请填写绑定证书的域名
server_name cms-back.ximo210.top;
# 请填写证书文件的相对路径或绝对路径
ssl_certificate /etc/nginx/cert/cms-back.crt;
# 请填写私钥文件的相对路径或绝对路径
ssl_certificate_key /etc/nginx/cert/cms-back.key;
ssl_session_timeout 5m;
# 请按照以下协议配置
ssl_protocols TLSv1.2 TLSv1.3;
# 请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;

location / {
# 请填写后端运行的端口
proxy_pass http://localhost:8080;
}
}

前端

Vue 项目打包

在 Vue 项目的根目录执行下面的命令,打包成 dist 目录(打包前记得将环境或者配置修改为服务器的)

1
npm run build

将 dist 目录重命名为 cms(名字自取)

将打包文件上传到服务器

可以使用 xftp 上传打包文件至服务器,也可以使用对应云服务器厂商自带的 WebShell(我使用的是腾讯云的 OrcaTerm)
这边将打包好的 cms 文件上传到/var/www文件夹下(文件路径可以自己选择)

修改文件权限

将 cms 目录的权限修改为 755,确保 Nginx 对该文件有访问权限

1
2
cd /var/www
chmod -R 755 cms

安装 Nginx

注:如果是从后端 Nginx 部分看过来的,可以直接跳到编辑配置文件,将内容添加到原有配置的后面即可
Ubuntu 下输入下面命令即可安装 Nginx

1
sudo apt install nginx

中间会询问是否继续安装,输入y回车即可
等待安装完成,可以输入下面命令查看 Nginx 服务状态

1
sudo systemctl status nginx

安装完成后,Nginx 服务会自己启动,可以看到 Nginx 服务已经正常运行

配置文件部分说明

Nginx 配置文件路径默认在/etc/nginx
可以输入下面命令查看 Nginx 配置文件位置

1
nginx -t

红框中即 Nginx 主要配置文件所在的位置
cd /etc/nginx到 Nginx 目录下,ls查看结构

  • nginx.conf 即 Nginx 的主要配置文件,可以直接在该文件中进行修改(大多数教程也是这么做的),但是如果以后部署的服务多起来,都放在一个配置文件中则会显得混乱和臃肿
  • 新版本的 Nginx 允许我们在 nginx.conf 中导入其他文件夹中的 .conf 文件,因此我们可以针对不同的服务,建立不同的 conf 配置文件,方便管理
  • 而 Nginx 已经为我们建好了一个文件夹,并且导入到了配置文件中,即 conf.d 文件夹,我们可以直接在该文件夹下新建和添加配置文件
  • 注:nginx.conf 中有关于 Nginx 整体的相关配置,但这里不多介绍,我们也不去修改
新建配置文件

/etc/nginx/conf.d路径下新建一个cms.conf文件,文件名可以自己取,文件后缀.conf

1
touch /etc/nginx/conf.d/cms.conf
编辑配置文件

使用 vim 打开编辑该文件

1
vim /etc/nginx/conf.d/cms.conf

输入i进入编辑模式(在英文输入法下)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
server {
# 监听的端口号(即想要访问的前端服务的端口)
listen 5173;
server_name localhost;

location / {
# 打包文件的路径
root /var/www/cms;
index index.html;
# 此处的 @router 实际上是引用下面的转发,否则在 Vue 路由刷新时可能会抛出 404
try_files $uri $uri/ @router;
}

# 由于路由的资源不一定是真实的路径,无法找到具体文件
# 所以需要将请求重写到 index.html 中,然后交给真正的 Vue 路由处理请求资源
location @router {
rewrite ^.*$ /index.html last;
}

# 将所有 ip:port/api 的请求转发到对应的后端地址(根据自己实际情况修改)
location /api {
# 填写后端服务的端口(如果不是同一台服务器则填写对应服务器的地址)
proxy_pass http://localhost:8080;
}
}

Esc退出编辑模式,输入:wq(包括:,在英文输入法下)后回车即保存退出

重启 Nginx

输入下面命令重启 Nginx 以应用修改后的配置文件

1
sudo nginx -s reload

云服务器放行端口

想要访问前端页面,需要将服务对应运行的端口(比如我这边就是在5173端口)放开,不然直接访问是访问不到的
在云服务器厂商找到对应云服务器的防火墙,并放行 5173 端口(对应你自己前端的运行端口)

绑定域名

编辑配置文件

依旧是编辑/etc/nginx/conf.d/cms.conf文件

1
vim /etc/nginx/conf.d/cms.conf

在原先的基础上修改

  • listen修改为 80,表示的是监听的端口,因为 http 请求默认访问的是 80 端口,举例来说当我们在访问www.baidu.com的时候其实访问的是www.baidu.com:80,不过 80 可以省略
  • server_name填入你要绑定的域名

修改完后按Esc退出编辑模式,输入:wq(包括:,在英文输入法下)后回车即保存退出

配置 SSL 证书

跟博客配置相同,本文不再赘述

这里附上配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
server {
listen 80;
# 前端绑定的域名
server_name cms.ximo210.top;
# 强制跳转https
rewrite ^/(.*) https://$server_name$request_uri? permanent;
}

server {
# SSL 默认访问端口号为 443
listen 443 ssl;
# 请填写绑定证书的域名
server_name cms.ximo210.top;
# 请填写证书文件的相对路径或绝对路径
ssl_certificate /etc/nginx/cert/cms.crt;
# 请填写私钥文件的相对路径或绝对路径
ssl_certificate_key /etc/nginx/cert/cms.key;
ssl_session_timeout 5m;
# 请按照以下协议配置
ssl_protocols TLSv1.2 TLSv1.3;
# 请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;

location / {
# 打包文件的路径
root /var/www/cms;
index index.html;
# 此处的 @router 实际上是引用下面的转发,否则在 Vue 路由刷新时可能会抛出 404
try_files $uri $uri/ @router;
}

# 由于路由的资源不一定是真实的路径,无法找到具体文件
# 所以需要将请求重写到 index.html 中,然后交给真正的 Vue 路由处理请求资源
location @router {
rewrite ^.*$ /index.html last;
}

# 将所有 ip:port/api 的请求转发到对应的后端地址(根据自己实际情况修改)
location /api {
# 填写后端服务的端口(如果不是同一台服务器则填写对应服务器的地址)
proxy_pass http://localhost:8080;
}
}

感谢

本文引用及相关文档和网站

手册 |Docker 文档

官方镜像站

Docker(黑马 文档)

引用惜寞部长,青鸟部长博客的相关内容,具体可以直接去友链寻找相关博客进行学习