企业部署,springboot+vue+vue,Linux上部署mysql与redis,docker中部署nginx,jenkins。完整详细。

企业项目部署全流程笔记

前言

涉及:Linux服务器,docker,Jenkins,nginx,springoot,vue,mysql,redis,git,

docker生成容器类型:MySqlRedis,Jenkins,Nginx,项目存放的容器。

注:!!!!!!!!!!!数据库不要存放在Docker中,而且存放会在使用时会有问题。!!!!!!!!!!

  • 存放 mysql 时、发现其账号密码只能是 root 和 123456 其余的密码会出现问题,显示登陆出错。

项目共用MySql,Redis。使用 Jenkins 进行自动化部署项目。前端项目全部存放到 Nginx 中,设置动静分离,子域名映射。容器间使用自定义网络进行通信。

1.登陆Linux服务器

笔者使用腾讯云2核4G,同时使用 Xshell 软件操作服务器。

登陆步骤准备:服务器公网Ip地址服务器密码(若未修改密码可在腾讯云邮箱中找寻初始密码)、服务器账号(默认为 root)

1.1、点击

在这里插入图片描述

1.2、填写公网IP

在这里插入图片描述

1.3、填写用户名

在这里插入图片描述

1.4、填写密码

在这里插入图片描述

1.5、成功

在这里插入图片描述

2、安装 Docker

要求

1、Docker 要求 CentOS 系统的内核版本高于等于3.10

2、若之前安装过,需先删除:

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

1、安装基本环境

地址

sudo yum install -y yum-utils

在这里插入图片描述

2、设置镜像仓库(若阿里云镜像安装失败则使用官方)
阿里云镜像:yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
官方镜像:
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo3、安装前先更新 yum 包索引
yum makecache fast4、安装最新版Docker docker-ce:社区版
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin5、启动
sudo systemctl start docker
(systemctl start docker.service  #后台启动,systemctl enable docker   #设置开机自动启动)6、运行镜像判断是否安装成功
sudo docker run hello-world注:可使用 docker version 查看版本信息

在这里插入图片描述

8、查看镜像
docker imagesREPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    9c7a54a9a43c   4 months ago   13.3kB
注:这个hello-world是我刚才编写的,并非自带的docker rm -f <containerid> 删除指定容器
docker ps # 查询容器
docker stop 容器名 # 停止容器
docker rmi 镜像名 # 删除镜像
docker ps -a # 查询所有容器状态
docker logs f28efc96ac5e # 日志
docker start -a ID # 启动容器容器ID/容器名称 -a参数是显示标准输出,“相当于”前台启动,不带-a参数相当于后台启动。
docker inspect 容器id # 查看容器详细信息docker rm -f $(docker ps -aq)
# docker ps -aq:列出所有容器的 ID,包括正在运行和已停止的。
# docker rm -f:删除所有列出的容器。 -f 选项表示强制删除,即使容器正在运行也会被停止和删除。
# 请注意,这个命令会永久删除所有容器,包括你可能想要保留的容器。确保在运行之前,你已经备份了需要保留的容器中的数据或设置。docker search image_name# 查询网络镜像
docker images# 查询本地镜像
docker exec -it 243c32535da7 /bin/bash # 进入容器

3、Docker 自定义网络

因 docker 容器间无法通信,所以在创建容器时设置网络,方便项目容器容器间访问,如果有这方面需要

3.1、生成自定义网络并测试

注:如下内容只作为讲解,观看原理,使用方式即可。后续会有详细步骤。

命令:docker network ls
发现有如下网络:
bridge :桥接 docker(默认)
none:不配置网络
host:和宿主机共享网络
(了解)container:容器网络联通(局限大,不建议)
# 我们直接启动命令默认末尾会带: --net bridge,即docker0,但是我们不使用这个,因为要使用到link关键字,这个关键字现在已经不使用了(弊端:无法通过域名进行访问)
docker run -d -P --name 容器名 --net bridge 1、创建自定义网络
命令:
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
# 解释
# docker network create:创建 Docker 网络的命令。
# --driver bridge:指定网络驱动程序。在这里,使用的是默认的桥接(bridge)网络驱动程序,这是 Docker 默认的网络驱动程序,用于在容器之间创建私有网络。
# --subnet 192.168.0.0/16:指定网络的子网。在这个例子中,你指定了一个 IP 地址范围为 192.168.0.0 到 192.168.255.255 的子网。
# --gateway 192.168.0.1:指定网络的默认网关。在这里,你设置了默认网关为 192.168.0.1。
# mynet:这是你为网络指定的名称,你可以根据需要自定义网络名称。2、查看网络是否创建成功命令
docker network inspect mynet
# config关键字下显示Subnet为 1921.68.0.0/16 Gateway下显示 192.168.0.13、创建并运行多个容器(用作测试容器间是否能够访问)
docker run -d -P --name 容器名1 --net mynet  
docker run -d -P --name 容器名2 --net mynet 
# -d:表示容器会以后台(detached)模式运行,也就是在后台运行容器,不会阻塞终端。
# -P:表示 Docker 会自动分配端口,将容器内部的端口映射到宿主机的随机端口上,使得容器的端口可以从外部访问。
# --name 容器名:为容器指定一个自定义的名称,你可以将 "容器名" 替换为你希望的名称。
# --net mynet:指定容器连接到名为 "mynet" 的 Docker 网络。这是一个自定义网络名称,你可以将其替换为你创建的网络的名称。4、再次查看网络,观察容器是否被分配网络
docker network inspect mynet5、使用IP进行容器访问,查看是否能够 Ping 通
docker exec -it 容器1 ping 192.168.0.3(这里的IP应该是容器2的IP地址)6、使用名字进行 Ping 测试
docker exec -it 容器1 ping 容器2# 注:上述两种方式均应成功

3.2、跨网络联通

上述创建了 192.168.0.0/16 的网络,表示在 192.168.x.x 的所有网络均可相互访问,若此时另一个网络 172.18.x.x 想要访问 192.168.x.x 时,是无法访问的。

1、将有172.18.x.x的网络与 mynet 相连
docker network connect mynet 容器名(即网络为 172.18.x.x 的容器)2、再次查看网络情况
docker network inspect mynet
发现,实际上是将此容器加入到 mynet 网络中,即一个容器,两个IP。3、测试是否能够 pingdocker exec -it 容器1 ping 容器2

4、创建镜像

注:可跳过,我们在创建容器时可指定镜像

我们一共需要创建如下镜像:

3、nginx : docker pull nginx:latest
4、Jenkins: docker pull jenkins/jenkins:latest5、查看镜像
docker images输出:
REPOSITORY        TAG       IMAGE ID       CREATED        SIZE
jenkins/jenkins   latest    c9101035cede   13 hours ago   478MB
nginx             latest    f5a6b296b8a2   5 days ago     187MB
hello-world       latest    9c7a54a9a43c   4 months ago   13.3kB6、创建自定义网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet

5、创建容器和数据库

5.0、容器的挂载

注:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

我们挂载目录时,不要放在home下即使要放,需要管理员权限,或者命令前加sudo ,不然会出现莫名其妙启动不了的错误

  • 同时,我们可以将宿主机上需要挂载的文件夹进行提权。如果不提权,可能会导致容器挂载的文件夹有东西但因为宿主机无法写入导致宿主机文件夹为空反过来使容器里面的文件夹也为空。
  • 其次,发现在使用nginx时即使将文件夹提升权限,创建后依然无文件,可能是我操作出错等等,但是还有方法,我们先创建好需要挂载的文件夹,然后创建nginx容器,注意此时不要挂载文件,创建好容器后将容器内对应文件夹内容复制到宿主机的对应需要挂载的文件夹中。然后删除容器,再次创建容器此时将挂载写上即可(注:这种方法只合适每次创建后内容都一样的容器)

5.1、安装Mysql

前言

以下内容只做参考,未实际使用!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

注:被 = 框起来的无需操作,这里只是作为演示,非要做会发现,必须要将密码设置为123456才能成功,且在挂载时不能事先创建文件夹,且容器的文件夹需要对照官网给的例子进行映射
================================================
1、创建Mysql容器并运行
docker run -d \--name my-mysql-container \-e MYSQL_ROOT_PASSWORD=your_root_password \-e MYSQL_DATABASE=your_database_name \-e MYSQL_USER=your_mysql_user \-e MYSQL_PASSWORD=your_mysql_password \-v /myDocker/mysql/conf:/etc/mysql/conf.d \-v /myDocker/mysql/data:/var/lib/mysql \-p 3306:3306 \--net bridge \mysql:5.7# docker run:用于启动一个容器。
#-d:表示在后台运行容器。
#--name my-mysql-container:给容器一个自定义的名称,这里是 "my-mysql-container",你可以根据需要更改它。
#-e MYSQL_ROOT_PASSWORD=your_root_password:设置 MySQL 的 root 用户密码。将 "your_root_password" 替换为你想要的密码。
#-e MYSQL_DATABASE=your_database_name:创建一个新的数据库并设置其名称。将 "your_database_name" 替换为你想要的数据库名称。
#-e MYSQL_USER=your_mysql_user 和 -e MYSQL_PASSWORD=your_mysql_password:可选的,用于创建一个新的 MySQL 用户并设置其密码。将 "your_mysql_user" 和 "your_mysql_password" 替换为你想要的用户名和密码。
#-v /path/to/your/mysql/data:/var/lib/mysql:这是挂载数据卷的部分。将 "/path/to/your/mysql/data" 替换为你本地系统上存储 MySQL 数据的目录路径。这将使 MySQL 数据在容器停止或删除时仍然保留在本地系统中。
#-p 3306:3306:将容器的 MySQL 端口(默认为 3306)映射到主机的相同端口,以便可以通过主机访问 MySQL 服务。
# --net bridge :指定网络
2、进入容器内部
docker exec -it mysql /bin/bashdocker exec -it mysql mysql -u root -p(直接登陆)3、登陆
mysql -uroot -p1234564、退出
exit (Ctrl+D)
========================================

分割线====

上述只是用来显示并非实际使用,如下则是实际教程、注Mysql并未部署在容器中,而是直接在Linux系统上使用。

1、查找已安装的MySQL软件包和CentOS7下还需要查找是否存在mariadb包:
rpm -qa|grep mysql
rpm -qa|grep mariadb
若存在包,则删除、没用则不用执行。没有输出即无包
rpm -e --nodeps mysql-libs-5.1.73-1.el6.x86_64
rpm -e --nodeps mariadb-libs-5.5.56-2.el7.x86_642、提升权限,由于 MySQL 安装过程中,会通过 MySQL 用户在 /tmp 目录下新建 tmp_db 文件,所以需要给 /tmp 目录较大的权限
chmod -R 777 /tmp3、检查依赖
rpm -qa|grep libaio
rpm -qa|grep net-tools
若不存在,则安装对应依赖
yum -y install libaio net-tools4、安装
先进入opt目录
cd /opt5、使用 wget下载并解压,在下载的过程中会显示进度条,包含 (下载完成百分比,已经下载的字节,当前下载速度,剩余下载时间)
wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.16-1.el7.x86_64.rpm-bundle.tar
tar -xvf mysql-5.7.16-1.el7.x86_64.rpm-bundle.tar6、解压并安装
当执行上述命令且下载完成后,会自动出现一行解压命令,此时我们只需回车即可
安装:
解压后会有若干包,但我们只需使用其中一部分,安装如下包
rpm -ivh mysql-community-common-5.7.16-1.el7.x86_64.rpm 
rpm -ivh mysql-community-libs-5.7.16-1.el7.x86_64.rpm
rpm -ivh mysql-community-client-5.7.16-1.el7.x86_64.rpm 
rpm -ivh mysql-community-server-5.7.16-1.el7.x86_64.rpm
注意:1. 安装 server 会比较慢;2. 如果前面第 1.3 步没检查好,在安装 mysql-community-server 会报错7、初始化 Mysql
mysqld --initialize --user=mysql8、查看并记住密码、“root@localhost:” 后面的就是初始化密码,要记下来,后面连接数据库会用到
cat /var/log/mysqld.log | tail -n 109、启动 MySQL 服务
systemctl start mysqld.service10、查看是否自启动
systemctl list-unit-files|grep mysqld.service
若输出:mysqld.service                                enabled 
则设置自启动
systemctl enable mysqld.sercice11、登陆
mysql -uroot -p刚才记下的密码
出现:Welcome to the MySQL即为登陆成功,若出现错误,看密码是否正确,其中若密码中存在需要转义的字符需要使用英文双引号括起来,如:ssdd"("ddd12、修改密码:因为初始密码为临时,会过期
ALTER USER 'root'@'localhost' IDENTIFIED BY '你的密码';
注:
1、复制时不要带 ; 因为带了会直接执行,不方便修改密码,当输入完成后需要添加上 ; 否则mysql以为你没有输入完。
2、密码太过简单会报错ERROR 1819 (HY000):
解决方法:
set global validate_password_policy=LOW; // 设置密码的验证强度等级为低(LOW)
set global validate_password_length=6; // 设置密码长度为6,最小为413、修改字符集
输入以下语句可以发现数据库和服务端的默认字符都是latin1,如果不修改容易出现乱码
show variables like 'character%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
解决方法:
输入 "vim /etc/my.cnf " 或用Xftp打开 "/etc/my.cnf " 文件进行编辑,在最后加上
character_set_server=utf8
init_connect=’SET NAMES utf8’14、重启Mysql服务
systemctl restart mysqld15、远程访问
输入以下语句查看MySQL的用户信息:
select host,user,authentication_string from mysql.user
输出:
+-----------+-----------+-------------------------------------------+
| host      | user      | authentication_string                     |
+-----------+-----------+-------------------------------------------+
| localhost | root      | *514C5DC7D34822064704BE6926512A4A84BC1677 |
| localhost | mysql.sys | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
+-----------+-----------+-------------------------------------------+
#发现都是localhost,即本地访问
#host:表示连接类型
#%:表示所有远程通过 TCP方式的连接
#IP地址:如 (192.168.1.2,127.0.0.1) 通过制定ip地址进行的TCP方式的连接
#机器名:通过制定i网络中的机器名进行的TCP方式的连接
#::1:IPv6的本地ip地址 等同于IPv4的 127.0.0.1
#localhost:本地方式通过命令行方式的连接 ,比如mysql -u xxx -p 123xxx 方式的连接。
#user:表示用户名
#同一用户通过不同方式链接的权限是不一样的。
#authentication_string:密码
#所有密码串通过password (明文字符串)生成的密文字符串。加密算法为MYSQLSHA1,不可逆。MySQL 5.7的密码保存到#authentication_string字段中不再使用password字段(在5.5中使用)。
15.1、因此下面给出了用户授权、创建用户、删除用户和修改密码的命令。
用户授权命令(该命令执行授权时如果发现没有指定的用户,则会直接创建一个新用户来完成授权):
grant 权限1,…权限n on 数据库名.表名 to 用户名@用户地址 identified by ‘密码’;
例如,授予通过网络方式登录的root用户,有对所有库、所有表的全部权限,密码设为”newpwd123”:
grant all privileges on *.* to root@'%' identified by 'newpwd123';
15.2、测试访问,就不讲了
注:记得将3306端口开放,如果是腾讯云就在安全组中添加规则,然后使用tcp:3306开放端口16、补充知识
16.1、查看Mysql版本 
mysqladmin -u root -p密码 –version 16.2、关闭Mysql服务
systemctl stop mysqld.service16.3、查看mysql服务状态
systemctl status mysqld16.4、连接数据库后修改数据库的字符集(其中mydb为数据库名)
alter table mytbl convert to character set 'utf8';16.5、修改数据库表的字符集(其中mytbl为表名)
alter table mytbl convert to character set 'utf8';16.6、创建Mysql用户
create user root identified by '123abc';16.7、修改用户名
update mysql.user **set** user='li4' where user='wang5';
flush privileges;  # 所有通过user表的修改,必须用该命令才能生效。16.8、删除用户
drop user user@host;16.9、修改当前用户的密码
set password = password('new_password')16.10、修改某个用户的密码
update mysql.user set password=password('new_password') where user='name';
flush privileges; # 所有通过 user表的修改,必须用该命令才能生效。

相关目录介绍

在这里插入图片描述

5.2、安装redis

1、下载:版本可以选择其他
wget http://download.redis.io/releases/redis-5.0.7.tar.gz2、解压、注意解压的目录,最好新建一个
cd /redis
tar -zxvf redis-5.0.7.tar.gz3、安装gcc依赖环境
yum install gcc4、编译与安装,这里可以在 cd /redis/redis-5.0.7
#切换到 redis-5.0.7 目录
cd /redis/redis-5.0.7
# 编译
make
# 安装
make install
默认安装路径为/usr/local/bin目录5、后台启动
Redis默认是无法进行后台启动的,需要修改配置文件
cd /redis/redis-5.0.7
找到 redis.conf 文件并打开
在文件中查找:daemonize 
发现其后跟着 no,我们将其修改为 yes,即:daemonize yes,然后保存
最后启动:
cd /usr/local/bin
redis-server /redis/redis-5.0.7/redis.conf
使用命令 ps -ef |grep redis 查看进程是否启动
输出为:
root      6370     1  0 16:56 ?        00:00:00 /usr/local/bin/redis-server *:6379
root      6384  2098  0 16:56 pts/0    00:00:00 grep --color=auto redis
或者使用客户端测试:输入命令
redis-cli
然后输入:ping,输出为 PONG 即可6、开机自启动设置
6.1、新建目录
mkdir -p /etc/redis   用于存放redis的配置文件(一般将原来的配置文件复制一份出来)
mkdir -p /var/log/redis 用于存放redis的日志文件
mkdir -p /var/redis/6379 用于存放redis的持久化文件(6379表示redis实例的端口号)6.2、将 redis.conf 配置文件(在/redis/redis-5.0.7下)复制到 /etc/redis 下并重命名为 6279.conf6.3、修改6379.conf内容
- 注释掉bind 127.0.0.1
- daemonize no  → daemonize yes
- logfile "/var/log/redis/6379.log" (注:查找logfile,并将其替换为此,下面的也一样)
- dir /var/redis/6379
- requirepass redis的密码 (注:这里可以设置密码,记得将注释取消)6.4、将redis解压后的目录中的utils下面的redis_init_script文件复制到/etc/init.d下面,并重命名为redis_63796.5、修改redis_6379文件 (注:正常情况下无需改动,观察一下即可)
#这个类似一个定义,这边的定义需要和使用的redis启动的使用的配置文件名字保持一致(不要后缀名)
REDISPORT=6379
#使用的配置文件。这边就是去读取/etc/redis下面的“6379.conf“配置文件
CONF="/etc/redis/${REDISPORT}.conf"
就需要修改以上两个配置6.6、将redis_6379服务设置为开机自启动
chkconfig redis_6379 on6.7、重启,查看进程 ps -ef |grep redis 7、打开与关闭命令 : 这里的 redis_6379 为/etc/init.d下面,重命名为redis_6379的文件名,可自行替换
# 打开redis命令:
service redis_6379 start# 关闭redis命令:
service redis_6379 stop8、设置密码后登陆
照成运行:
cd /usr/local/bin
redis-cli
发现可以,但是此时随意输入命令发现无法运行,此时我们有两种方法
- 已经运行 redis-cli 的情况下 ,我们输入 auth redis的密码
- 未运行 redis-cli 的情况下 ,我们输入 redis-cli -a redis的密码
返回 OK 则表示成功

6、Docker部署Nginx

1、下载
docker pull nginx2、创建挂载的文件夹,(但第一次创建容器不进行挂载,而是先创建容器然后将容器里需要挂载的文件复制到我们在Linux上真实的文件夹)
注:如果直接挂载,由于linux下的文件夹都为空会导致容器内也变成空
# 创建挂载目录
mkdir -p /home/nginx/conf
mkdir -p /home/nginx/log
mkdir -p /home/nginx/html
mkdir -p /home/nginx/ssl- /home/nginx/conf存放nginx的配置信息
- /home/nginx/log存放日志信息
- /home/nginx/html存放你的前端网页
- /home/nginx/ssl如果想使用https,就需要这个文件夹,存放证书# 提升权限
chmod 777 -R /home/nginx/conf
chmod 777 -R /home/nginx/log
chmod 777 -R /home/nginx/html
chmod 777 -R /home/nginx/ssl3、创建容器并复制到宿主机
# 生成容器
docker run --name nginx -p 80:80 -d nginx
# 将容器nginx.conf文件复制到宿主机
docker cp nginx:/etc/nginx/nginx.conf /home/nginx/conf/nginx.conf
# 将容器conf.d文件夹下内容复制到宿主机
docker cp nginx:/etc/nginx/conf.d /home/nginx/conf/conf.d
# 将容器中的html文件夹复制到宿主机
docker cp nginx:/usr/share/nginx/html /home/nginx/4、删除创建的容器
# 找到nginx对应的容器id
docker ps -a
# 关闭该容器
docker stop nginx
# 删除该容器
docker rm nginx# 删除正在运行的nginx容器
docker rm -f nginx5、再次创建容器,此时加入挂载文件夹以及自定义网络,加入自定义网络后容器间才能直接访问,这样前端才能访问后端
docker run \-p 80:80 -p 443:443 \--name nginx \-v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \-v /home/nginx/conf/conf.d:/etc/nginx/conf.d \-v /home/nginx/log:/var/log/nginx \-v /home/nginx/html:/usr/share/nginx/html \-v /home/nginx/ssl:/etc/nginx/ssl \--net mynet \-d nginx:latest
# 注:这里创建时还映射了443端口,如果想通过https+域名访问,这个是必不可少的!!!!!!!!! 7、进入容器,更新nginx
//修改nginx配置,在不能重启的情况下,可以无需重新启动Docker容器即可重新加载新配置。Nginx可以hot-reload配置而不重新启动。
//查询nginx所在容器id:docker ps -a
docker ps -a
//测试nginx配置
docker exec 容器id nginx -t 
//重新加载nginx配置
docker exec 容器id  nginx -s reload 
# 注:上述可能刷新失败,因为其要等到无连接后才能够刷新

6.1、配置文件原理介绍

这个之所以拿出来讲,是因为是重点也是难点,接下来会一步步慢慢讲!

原理介绍,可跳过,后面会有详细配置信息

首先,我们开启nginx后且可以直接通过IP地址访问到nginx页面时,表示初步部署成功!

但是,还有若干问题:

1、 如果你的宿主机的端口号设置的不是80,那么在进行IP访问时一定要加上端口号才能访问。
像这样:`-p 80:80` ,设置时才不需要端口号直接使用IP访问。同时需要nginx开启端口监听

我的需求是,公网IP是唯一的,但是会有若干域名指向此地址,且不同域名表示不同的前端项目,如何实现呢?

在实现之前,我们要了解一下配置文件某些东西的作用,下面是默认配置文件(default.conf)的内容,它在创建是就被我手动挂载到了/home/nginx/conf/conf.d 下。(注:我将注释的代码全部去除,方便讲解)

server {listen       80; # IPV4类型的监控容器内的80端口,由于我宿主机也设置为80,两者结合才是无需使用端口号的原因listen  [::]:80; # IPV6类型的监听80端口server_name  localhost; # 重点,下面讲# 当请求地址只有IP时,会走这里location / {root   /usr/share/nginx/html; # 此用处为,会去容器下的这个目录寻找目标文件index  index.html index.htm; # 如果目标文件知道了,就不需要执行此处,若未找到,则在目标目录下下载是否有名为index.html index.htm 的文件,有则返回,无则404.由请求于只有IP,没有带其他目录所以一定会走这里。}# 当请求来了之后但是由于某些原因导致发生500等5开头的错误,会走这个error_page   500 502 503 504  /50x.html;location = /50x.html {root   /usr/share/nginx/html;}
}

很显然,这只是一个server结果,完整的配置文件不止这些,在 /home/nginx/conf/ 下有一个nginx.conf文件,两者组成形成完整的配置文件。

2、在我们初始的配置文件中有这个设置server_name localhost;,文件地址为 /home/nginx/conf/conf.d、我们明明使用的公网IP,但这里默认文件的设置却为本机地址,那为啥那个访问成功呢?

先说说一个请求到 nginx 容器并进行转发的全过程:

​ 首先若使用公网IP进行访问,43.126.94.119 因为无论宿主机还是nginx容器,进行端口映射的值都为80,且nginx设置了端口监听 listen 80; ,所以可以不添加端口号直接使用IP进行访问。

​ 由于有端口映射,所以这个请求会直接进入nginx,此时

server 模块中的 server_name 发挥作用,会从请求头中的 Host 获得值,可以是域名也可以是 IP ,

若是IP

则 会与所有server 模块中 server_name 的值进行比较,若有就转发给对应 server 模块,若无就会走默认的server 模块,

何为默认模块?即 server 中设置了这个参数 listen 80 default_server;,如果如果所有都没设置,会默认走第一个。

若是域名

同样进行域名匹配,若无,则走默认模块或者默认模块也无则走第一个模块

注:当你使用IP访问,但所有 server 中的 ``server_name 值都为域名时,此时server_name 失效,会走默认模块或者第一个

server_name 值的三种情况

  • localhost
  • 域名
  • IP
依据上述原理,我们实现简易版的请求转发,有几种情况情况一:
当我们使用公网IP访问,此时有两个 server模块
- 第一个模块的 server_name 值为:localhost,有一个 location / {}模块,即简写版server_name  localhost; # 重点,下面讲location / {}- 第二个模块的 server_name 值为:43.137.94.117,有一个 location / {}模块,即简写版server_name  43.137.94.117; # 重点,下面讲location / {}
若请求地址为 43.137.94.117 时 会走第 二 个模块 (因为模块二匹配成功)情况二:
同样两模块,但此时location不同
- 第一个模块的 server_name 值为:localhost,有一个 location / {}模块,即简写版server_name  localhost; # 重点,下面讲location / {}- 第二个模块的 server_name 值为:43.137.93.117,有一个 location / {}模块,即简写版server_name  43.137.94.117; # 重点,下面讲location ^~/gw {}
若请求地址为 43.137.94.117 时 会走第 1 个模块 (因为模块都匹配不成功,且无默认模块,所以走第一个)
若请求地址为 43.137.94.117/gw 时 会走第 2 个模块 (因为 模块二 匹配成功,所以走第二个)注:^~/gw 表示无论/gw前面是啥都进行匹配

行文至此,依旧没有阐述如何在I域名不同但都指向同一IP下,访问不同域名可进入不同项目。

但实际上已经说了。

使用 server_name 的特性,将其值设置为不同域名即可

6.2、配置https与域名进行访问

1、首先,我们得判断nginx是否能够部署ssl,查询方法

进入nginx容器,cd /sbin 目录下,运行 nginx -V 命令,查看输出,若输出中存在:docker exec -it nginx /bin/bash 表示能够部署,若没有,则需要先安装,安装方法自行了解,我使用的容器nginx里面是自带的,不用额外配置

2、获取ssl证书,腾讯云有免费的ssl证书,申请后,然后到我的证书界面,选择右边的下载,选择Linux下nginx的下载,会获得一个压缩包,解压后有4个文件,然后将4个文件全部复制到服务器我们刚才创建的ssl目录下。

3、配置配置文件

在腾讯云我的证书那一块,右边有一个部署,点进去有在linux下的nginx如何部署https的教程。可以一步步对照

我们在 /home/nginx/conf/conf.d 目录下创建一个配置文件 gw.conf ,文件内容如下:

# 处理https请求的模块
server {listen 443 ssl; #ssl,监听端口server_name lvguidizi.com; # 域名ssl_certificate /etc/nginx/ssl/lvguidizi.com_bundle.crt; # 容器路径下的ssl文件夹下的.crt文件ssl_certificate_key /etc/nginx/ssl/lvguianzi.com.key;# 容器路径下的ssl文件夹下的.key文件# 下面的 4 行按照腾讯云教程来,个个教程有可能有差异,所以哪里的服务器用哪里的教程ssl_session_timeout 5m;ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on;# 我们做一个跳转,当通过域名访问时,将其跳转到 https://域名/gw 下,当然,你也可以不这样做location / {# 这意味着任何访问网站根目录的请求都会被重定向到 https://lvguidianzi.com/gw 这个 URL。rewrite ^/(.*) https://lvguidizi.com/gw;}# ^~/gw:表示无论/gw前面是啥只要后面以这个结尾都会进入这里,# 作用,会去你root设置的文件夹下寻找你location设置的/gw文件夹,并在文件夹下寻找你index设置的 indez.html文件location ^~/gw {# 这个块处理以 /gw 开头的 URL 路径的请求。它使用 try_files 指令尝试寻找匹配的文件,如果找不到文件,则会重定向到 /gw/index.html; 页面。# 这个块还设置了 root 和 index 指令,以指定根目录和默认索引文件。try_files $uri $uri/ /gw/index.html;root /usr/share/nginx/html;index index.html;}# 这个用来做动静分离,相当于此路径下存放图片和一些其他文件# 同样,他会去 root+location的路径下找,相当于/usr/share/nginx/html/file/location /file/ {root	/usr/share/nginx/html/;autoindex      on; # 列出访问目录}#location ^~/openApi/ {
#  proxy_pass      http://172.16.0.12:9999/openApi;
#  proxy_set_header Host $host; # 这个指令设置了请求头中的 "Host" 字段,将其值设置为客户端请求中的 "Host" 值。这是为了确保后端服务器能够正确识别客户端请求的主机名。
#  proxy_set_header X-Real-IP $remote_addr; # 这个指令设置了一个自定义请求头 "X-Real-IP",将其值设置为客户端请求的真实 IP 地址。这可以帮助后端服务器获取客户端的真实 IP 地址。
#  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 这个指令设置了另一个自定义请求头 "X-Forwarded-For",将其值设置为 $proxy_add_x_forwarded_for,它包含了所有中间代理服务器的 IP 地址。这有助于追踪请求经过的代理服务器链。
#  # 这两个指令用于配置 Nginx 内部的请求头哈希表的大小。这些配置项通常不需要手动设置,除非您在配置文件中有特殊的需求。
#  proxy_headers_hash_max_size 512;
#  proxy_headers_hash_bucket_size 64;
#}#location ^~/api/ {
#  proxy_pass      http://172.17.0.1:8081/;
#  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_headers_hash_max_size 512;
#  proxy_headers_hash_bucket_size 64;
#}error_page  404    /404.html;# 这个指令指定了处理状态码 497 的方式。状态码 497 表示客户端应该将请求转发到另一个地址,通常是由于客户端请求协议与服务器配置的协议不匹配。在这里,当发生状态码 497 时,# Nginx 会将请求重定向到 https://$host$uri?$args;,这意味着它将使用相同的主机名和请求 URI 重新发送请求,但使用 HTTPS 协议。error_page 497  https://$host$uri?$args;error_page  500 501 502 503 504  /50x.html;# 这个 location 块定义了 /50x.html 页面的位置。它告诉 Nginx 在根目录的 html 子目录下寻找 50x.html 文件。这是用于定义错误页面的位置。location = /50x.html {root   html;
}}   # 处理http请求的模块
server {listen       80;listen  [::]:80;server_name lvguidizi.com;location / {# 当我们以http+域名方式进行访问时,会走到这里,然后会将http转换为https重新请求,就会回到上面的模块了return 301 https://$host$request_uri; }  }
# 处理公网IP的请求
server {listen       80;listen  [::]:80;server_name 43.136.9.118;location / {# 如果是公网IP访问,如果没有进行出来就会走默认模块,也就是nginx自动创建的第一个配置文件,也就是我们部署好nginx时访问网页会出现的 welcome to nginx。所以我们也需要跳转,return 301 https://lvguidizi.com/gw;}  }

配置文件设置好后,我们需要在html文件夹下新建一个gw文件夹并创建一个index.html文件,然后就可以通过https://域名方式测试访问了,同时,我们也可以将打包好的vue项目放入gw文件夹下,就会自动访问了。

注:如果你觉得都配置好了但无法访问,可能有以下原因:

1、你的服务器443端口未开放(腾讯云是开放安全组),或者说你的nginx容器的443端口未映射(两者都要有)

2、你的ssl证书没用绑定到域名。

3、你的域名没用绑定到你的服务器公网IP

4、你的域名没有备案

5、配置文件完成后需要刷新nginx

6、配置文件中ssl证书名字或者路径设置错误,记得是容器路径

7、你的配置文件中 location 和root 模块组成的访问路径与你实际请求路径不同

6.3、配置同一域名部署多vue项目

假设有a,b两个vue项目。

1、在a项目的路由文件中进行如下配置(就是vue存放路由跳转的文件):

// 如果你的路由配置文件中没有这个,就新添一个
export default new VueRouter({base:'/a/', // 相当于在每一个路由跳转的路径前面加一个/a/路径}

2、在项目b也加入如上配置,只不过 base:'/a/' 改为 base:'/b/'

3、如果是vue2就在 config文件夹下的 index.js 下配置如下东西(b项目也记得按照规则改变):

...
build: {
assetsPublicPath: '/a/', // 将这个变量设置为你在路由上设置的路径,记得一致,这个是配置公共资源访问路径的选项,因为你的vue项目不在根目录下了,所以这里也要变
}
...

4、修改nginx配置文件

# 增加一个 location
location ^~/a {try_files $uri $uri/ /a/index.html;root /usr/share/nginx/html;index index.html;}
location ^~/b {try_files $uri $uri/ /b/index.html;root /usr/share/nginx/html;index index.html;}

5、在nginx的html目录下,就是存放vue项目的根目录。创建两个文件夹a,b然后在文件夹下存放vue项目,然后刷新配置文件。

6、附加:因为vue项目会访问后端,如果是springboot,此时我们需要在nginx里增加一个代理。(题主不清楚是不是一定要,但是题主使用若依的前端vue是必须要这样才能访问后端。正常情况下直接输入后端地址是可以访问到的,但是若依的前端加上去后就不能通过前端访问后端了)

# 这个路径 /prod-api/ 是要与前端vue项目里面的一致
location ^~/prod-api/ { proxy_pass      http://172.16.0.12:9999/; # 你的公网IP或者内网IP加上后端的端口号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_headers_hash_max_size 512;proxy_headers_hash_bucket_size 64;
}

前端若依里面有个文件 .env.production ,里面有如下代码:

# 页面标题
VUE_APP_TITLE = 若依管理系统# 生产环境配置
ENV = 'production'# 若依管理系统/生产环境
VUE_APP_BASE_API = '/prod-api' # 这个就是要与nginx里面一致的东西了

7、docker部署 Jenkins

!!!!!!!!!!!!!!!!!!!重难点!!!!!!!!!!!!!!!!!!!!

如果单纯按照网络教程来,会逐渐迷惑,甚至100个教程有一百种方法。。。

首先,我们讲一下为啥需要在 Docker 里面使用 jenkins ?

因为方便,jenkins配置啥的很多,新手一不小心就错了,此时如果在宿主机上,就很难去一键清零,但是Docker不一样,将容器删除再创建就又是一条好汉了。

其次,接下来教程默认你已经安装好docker了,话不多说开干!

前言:自动化部署流程首先,我们创建运行jenkins容器,然后登陆jenkins,设置好gitee,jdk,maven,ssh等等。记得在我们的项目的根目录(如果是多模块项目,就在启动模块的根目录)下创建Dockerfile文件,然后就是创建maven项目,在项目设置里,设置好需要git的文件路径,然后设置需要打成jar包的模块。然后设置shell语句。- gitee:存放我们的项目代码,
- jdk,maven:打成jar包需要的环境,jenkins自带jdk,但如果是最新的jenkins是jdk11,所以要么我们创建容器时控制为jdk8的版本要么在jenkins的系统设置里面手动修改(此修改需要在宿主机安装jdk,比较麻烦),maven是没有自带的,需要我们手动安装或者自动安装,没啥区别。
- ssh :推送,相当于将我们创建好的jar推送到指定服务器上运行,因为是在容器里面生成的jar包,
- Dockerfile文件:用来创建我们项目的docker镜像,只有创建镜像才能依据镜像创建容器,才能运行jar包1、在jenkins中我们需要挂载某些文件,但是如果你挂载在宿主机的文件夹没用权限,那么g了,当你挂载创建完成后,会发现文件夹空无一物。所以我们需要在宿主机下先创建文件夹。然后提升文件夹权限。
mkdir -p /common/jenkins_home # 创建文件
chmod 777 -R /common/jenkins_home # 提升权限
chmod 777 -R /var/run/docker.sock # 下面两个权限提升是以防万一,这两个文件夹作用等下说
chmod 777 -R /usr/bin/docker2、让Jenkins 容器里面能够使用宿主机的 docker 命令
在自动化部署时,我们在执行容器,镜像创建时是在jenkins里面的,但是正常情况下jenkins容器里面用不了容器外的docker命令,所以我们这里将docker命令需要的东西进行映射一下,也就是挂载。所以先将用到的文件夹提升权限,怕需要。需要挂载的文件夹有这两个:
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \3、创建并运行jenkins容器
docker run -d  -p 8080:8080 -p 50000:50000 \
--net mynet --restart=on-failure \
-v /common/jenkins_home:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
--name jenkins jenkins/jenkins:lts-jdk8
# 解释:
-p 8080:8080:端口8080用于Jenkins的Web界面
-p 50000:50000用于Jenkins的Slave节点通信。Slave节点是用于执行构建作业的工作节点。--net mynet:这个是我自己创建的自定义网络,容器间通信使用--restart=on-failure: 这部分指定了容器在失败时应该自动重启。如果Jenkins容器崩溃或失败,Docker将尝试重新启动它。-v /common/jenkins_home:/var/jenkins_home \:就是查看jenkins初始密码和一些其他文件,所以需要挂载-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \:这两个是运行docker命令需要的--name jenkins:指定容器名字jenkins/jenkins:lts-jdk8:指定自带jdk版本为8运行 docker ps 命令,如果在运行的容器列表找到了jenkins表示创建并运行成功!
CONTAINER ID   IMAGE                      COMMAND                  CREATED         STATUS         PORTS                                                                                      NAMES
7ad88fe4f57b   jenkins/jenkins:lts-jdk8   "/usr/bin/tini -- /u…"   27 hours ago    Up 27 hours    0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:50000->50000/tcp, :::50000->50000/tcp   jenkins         4、通过服务器加端口访问jenkins:如119.168.1.3:8080,服务器就是你自己的公网IP,端口号是创建时设置的。5、等它加载会,会让你输入密码,这个秘密存在的地址会在网页上显示,可以通过路径打开文件获取6、密码输入完后会有两个选择,安装推荐的插件和选择插件来安装。我们选择安装推荐的插件,然后就是等待下载完成7、会显示让你创建第一个用户,一次填写好并记下来,后面会用到。

好,下面就需要图文并茂了:

7.8、先下载插件,登陆后选择左边的 Manage Jenkins 选项,就是带一个小齿轮的,相当于设置,然后下滑选择 Manage Plugins

在这里插入图片描述

在这里插入图片描述

7.9、分别下载如下三插件,Maven Integration,, gitee,Publish Over SSH,下面输入框里面是简写,也能找到,第二张图是找到后勾选然后点击不重启安装

在这里插入图片描述

在这里插入图片描述

7.10、点击全局设置

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

私人令牌 - Gitee.com

注意:私人令牌记得保存下来,获得后回到jenkins,将令牌输入,下面的ID和描述不用填,直接保存,然后就和我的一样有一个选项了,直接选择

在这里插入图片描述

7.11、SSH

在这里插入图片描述

在这里插入图片描述

其余的保持默认即可

然后返回设置,这次点击第一行的中间那个

在这里插入图片描述

7.12、设置 Global Tool Configuration 开头的maven和jdk都不用管,我们找到下面的maven

在这里插入图片描述

7.13、创建maven项目

这里就正式开始制作自动化部署了,在制作之前,我们需要先准备一点东西。

1、在代码项目的根目录下,或者多模块项目的启动模块的根目录下创建一个制作代码项目镜像的文件:Dockerfile

注:记得将此文件上传至 gitee

在这里插入图片描述

FROM java:openjdk-8u111
VOLUME /tmp
ADD target/ruoyi-admin.jar ruoyi-admin.jar
EXPOSE 9999
ENV TZ=Asia/Shanghai
ENV JAVA_OPTS="-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m"
ENTRYPOINT ["java","-jar", "$JAVA_OPTS","/ruoyi-admin.jar"]- FROM java:openjdk-8u111 :基础镜像是 java:openjdk-8u111,表示基于 OpenJDK 8u111 版本的 Java 运行时环境。
- VOLUME /tmp  在容器内创建一个临时卷,通常用于存储临时文件或持久化数据。
- ADD target/ruoyi-admin.jar ruoyi-admin.jar将宿主机上的 target/ruoyi-admin.jar 文件复制到容器内,并命名为 ruoyi-admin.jar。因为jar包在此文件运行前就创建好了,jar创建的设置在下面会讲到。为什么地址是 target/ruoyi-admin.jar?因为在下面的设置及其运行结果看,在执行这几行代码前,整个项目已经处于workspace/ruoyi-admin/下了。workspace是jobs/目录下的一个文件夹。 jobs 是jenkins专门用来存放创建好的maven项目。里面包含项目相关的东西
- EXPOSE 9999就是你代码项目启动需要的端口号
- ENV TZ=Asia/Shanghai 时区
- ENV JAVA_OPTS="-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m"初始堆内存大小,最大堆内存大小,元空间初始大小,元空间最大,若超出则垃圾回收
- ENTRYPOINT ["java","-jar", "$JAVA_OPTS","/ruoyi-admin.jar"]定义容器启动时要执行的命令。它启动了一个 Java 进程,运行 ruoyi-admin.jar

2、正式创建maven项目

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

点击添加,配置用户名和密码

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

命令:

clean install -pl ruoyi-admin -am -amd# 一般写上面就行,下面是补充clean package  -pl  ruoyi-admin -am -amd   -P test -Dmaven.test.skip=true
clean package 清除打包
-pl ruoyi-admin -am -amd 指定项目下的子模块
ruoyi-admin 是子模块的项目名
-P test 指定构建环境,项目配置文件的名字
-Dmaven.test.skip=true 跳过maven测试

在这里插入图片描述

在这里插入图片描述

下面的表示当项目的jdk,maven都准备好了,jar也打好了之后要执行啥东西,此时也就是开始先清除之前旧东西(如果有),然后开始运行 Dockerfile 文件创建镜像,然后通过镜像创建容器,然后运行容器,然后查看容器是否运行,之后就部署好了

请添加图片描述

这里的shell代码为

docker stop ruoyi-admin || true 
docker rm ruoyi-admin || true
docker rmi ruoyi-admin || true
docker build -t ruoyi-admin ruoyi-admin/
mkdir -p common/logs/ruoyi-admin
chmod 777 -R common/logs/ruoyi-admin
docker run -d -p 9999:9999  -v /common/logs/ruoyi-admin:/home/ruoyi/logs --net mynet --name ruoyi-admin ruoyi-admin# 解释:
- docker stop ruoyi-admin || true 如果有旧容器就停止,没有就返回true,继续- docker rm ruoyi-admin || truedocker rmi ruoyi-admin || true同上,有就删除容器与镜像- mkdir -p common/logs/ruoyi-admin
chmod 777 -R common/logs/ruoyi-admin创建文件夹和提升权限- docker build -t ruoyi-admin ruoyi-admin/这个命令从位于ruoyi-admin/目录中的Dockerfile构建一个名为ruoyi-admin的Docker镜像,并使用-t选项为镜像指定名字。以workspace文件夹为始- docker run -d -p 9999:9999  -v common/logs/ruoyi-admin:/var/logs --link redis:redis --link mysql:mysql --net mynet --name ruoyi-admin ruoyi-admin-d:以后台模式运行容器。-p 9999:9999:将主机的9999端口映射到容器的9999端口。-v common/logs/ruoyi-admin:/var/logs:将主机上的common/logs/ruoyi-admin目录映射到容器的/home/ruoyi/logs目录,用于日志持久化。我使用的若依,它已经帮我配置好了日志文件,所以可以直接使用,如果是其他的项目需要自己在springboot项目里面创建logback.xml 去进行设置,具体百度--link redis:redis --link mysql:mysql:将容器连接到名为redis和mysql的其他容器。--net mynet:将容器连接到名为mynet的自定义网络。--name ruoyi-admin:为容器指定名称为ruoyi-admin。ruoyi-admin:指定要运行的Docker镜像。
===============================
如果想将此代码放入一个sh文件,由于win和linux差别,win创建*.sh文件是无法直接在linux下运行,需要将文件通过
chomd +x ./q.sh
命令,将sh变为可执行文件。

至此,所有配置完成,然后保存。回到开始页面,开始构建项目。初次构建会下载maven和jdk所以会慢。然后可以查看日志如果构建失败看看哪一步出错

8、杂项

1、导入字体文件方式

  • 使用nginx的动静分离,将字体文件放入其中,然后在项目中引用其路径,然后在nginx配置动静分离的配置文件中修改其location,增加一项:add_header Access-Control-Allow-Origin *;# 解决字体文件跨域问题
location /file/ {root	/usr/share/nginx/html/;autoindex      on; # 列出访问目录add_header Access-Control-Allow-Origin *;# 解决字体文件跨域问题}
  • 在存储在本地,发现可以访问到,但是网页会显示加载字体文件失败, 在.gitignore 文件中添加 *.ttf binary,即,你字体文件的后缀,这样就可以了,但是我不理解为啥可以…

注:这样确实可以成功,但是有个问题,字体文件比较大,小的几m大的10几m,对于网页访问来讲,加载很慢,影响用户体验,所以我们需要精简一下字体文件,将我们项目中没有用到的字体去除然后重新生成字体文件。

这里使用到 字蛛

无论是上面的哪种方法,都需要将字体包精简,而字蛛就是运作原理是:

新建一个index.html文件,在文件中导入我们自定义的字体以及若干文字,然后通过字蛛进行操作生成精简版的字体文件,这个文件里面的字体个数取决于你在html文件中写入的不同文字个数。

使用字蛛

1、确保你的node版本是16左右,字蛛使用需要的npm版本有一定要求,好像是6.9.0以上,这里我们通过安装nodejs去升级npm,

2、使用管理员权限打开cmd,并输入一下命令

npm install font-spider -g

如果保存查看两方面,是否为管理员启动,npm版本是否高于6.9.0.

3、为字蛛安装环境变量。一般情况下在nodejs安装目录下的 E:\nodejs\node_cache 目录有一个font-spider.cmd文件,我们找到这个路径,打开环境变量设置,设置系统环境变量中选择 path 新建一个,路径就选择 E:\nodejs\node_cache。然后确认。

4、我们随便在一个文件夹下,将自定义的字体文件放入这个文件夹下,然后在文件夹下创建一个index.html,文件,假设字体文件名为 a.ttf。那么在index.html文件下编写如下内容:

<!DOCTYPE html>
<html lang="en">
<style>@font-face {font-family: 'a';src: url("a.ttf") format('truetype');font-weight: normal;font-style: normal;}
</style>
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<div>这里写出所有你想要的文字,字蛛会自动扫描这个文件里面的文字,然后基于你给的文字生成一个字体文件</div>
</body>
</html>
<style>div{font-family: "a";}
</style>

然后使用管理员权限,打开cmd,并且切换目录到这个文件夹下。即存在字体文件a和index.html文件的文件夹。

然后执行命令:

font-spider index.html

经过一阵运行后你会发现,在文件夹下生成了一个文件夹 .font-spider,这个文件夹下存放的是你原来的字体文件a。而生成的新字体文件是在和 index.html 同级下,也是叫 a.ttf 即新文件覆盖了旧文件。然后我们就可以使用这个文件了,会发现这个文件大小变小了很多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/148808.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

string类的模拟实现(万字讲解超详细)

目录 前言 1.命名空间的使用 2.string的成员变量 3.构造函数 4.析构函数 5.拷贝构造 5.1 swap交换函数的实现 6.赋值运算符重载 7.迭代器部分 8.数据容量控制 8.1 size和capacity 8.2 empty 9.数据修改部分 9.1 push_back 9.2 append添加字符串 9.3 运算符重载…

[学习笔记]ARXML - Data Format

参考AUTOSAR文档&#xff1a; https://www.autosar.org/fileadmin/standards/R22-11/FO/AUTOSAR_TPS_ARXMLSerializationRules.pdfhttps://www.autosar.org/fileadmin/standards/R22-11/FO/AUTOSAR_TPS_ARXMLSerializationRules.pdf 编码 arxml只允许使用UTF-8编码&#xff…

小谈设计模式(19)—备忘录模式

小谈设计模式&#xff08;19&#xff09;—备忘录模式 专栏介绍专栏地址专栏介绍 备忘录模式主要角色发起人&#xff08;Originator&#xff09;备忘录&#xff08;Memento&#xff09;管理者&#xff08;Caretaker&#xff09; 应用场景结构实现步骤Java程序实现首先&#xff…

VC++创建windows服务程序

目录 1.关于windows标准可执行程序和服务程序 2.服务相关整理 2.1 VC编写服务 2.2 服务注册 2.3 服务卸载 2.4 启动服务 2.5 关闭服务 2.6 sc命令 2.7 查看服务 3.标准程序 3.1 后台方式运行标准程序 3.2 查找进程 3.3 终止进程 以前经常在Linux下编写服务器程序…

小程序中如何开启分销

小程序共享微信生态&#xff0c;商家可以通过小程序来快速扩大自己的销售渠道&#xff0c;其中一个非常受重要的功能就是分销。通过开启分销功能&#xff0c;商家可以让更多的人参与到销售中来&#xff0c;从而提高销售额。那么&#xff0c;在小程序中如何开启设置分销呢&#…

Qt model/view 理解01

在 Qt 中对数据处理主要有两种方式&#xff1a;1&#xff09;直接对包含数据的的数据项 item 进行操作&#xff0c;这种方法简单、易操作&#xff0c;现实方式单一的缺点&#xff0c;特别是对于大数据或在不同位置重复出现的数据必须依次对其进行操作&#xff0c;如果现实方式改…

1802_在Linux系统上开发ARM单机片机嵌入式软件

全部学习汇总&#xff1a; GreyZhang/little_bits_of_linux: My notes on the trip of learning linux. (github.com) 1. 在Linux上也有嵌入式的开发环境&#xff0c;或许还有很多。不过&#xff0c;我现在接触到的大部分还是Windows居多。这一份文件介绍的是一个mbed platform…

OK3568 forlinx系统编译过程及问题汇总

1. 共享文件夹无法加载&#xff1b;通过网上把文件夹加载后&#xff0c;拷贝文件很慢&#xff0c;任务管理器查看发现硬盘读写速率很低。解决办法&#xff1a;重新安装vmware tools。 2. 拷贝Linux源码到虚拟机&#xff0c;解压。 3. 虚拟机基本库安装 forlinxubuntu:~$ sudo…

《C和指针》笔记33:指针数组

除了创建整型数组一样&#xff0c;也可以声明指针数组。 int *api[10];为了弄清这个复杂的声明&#xff0c;我们假定它是一个表达式&#xff0c;并对它进行求值。下标引用的优先级高于间接访问&#xff0c;所以在这个表达式中&#xff0c;首先执行下标引用。因此&#xff0c;a…

连续爆轰发动机

0.什么是爆轰 其反应区前沿为一激波。反应区连同前驱激波称为爆轰波。爆轰波扫过后&#xff0c;反应区介质成为高温高压的爆轰产物。能够发生爆轰的系统可以是气相、液相、固相或气-液、气-固和液-固等混合相组成的系统。通常把液、固相的爆轰系统称为炸药。 19世纪80年代初&a…

Spring Boot中的@Controller使用教程

一 Controller使用方法&#xff0c;如下所示&#xff1a; Controller是SpringBoot里最基本的组件&#xff0c;他的作用是把用户提交来的请求通过对URL的匹配&#xff0c;分配个不同的接收器&#xff0c;再进行处理&#xff0c;然后向用户返回结果。下面通过本文给大家介绍Spr…

Vue中如何进行网页截图与截屏

在Vue中实现网页截图与截屏功能 网页截图与截屏功能在许多Web应用程序中都非常有用。Vue.js作为一个流行的JavaScript框架&#xff0c;提供了许多工具和库来简化网页截图和截屏的实现。本文将介绍如何使用Vue来实现一个网页截图和截屏功能的示例&#xff0c;包括使用html2canv…

联想M7216NWA一体机连接WiFi及手机添加打印机方法

联想M7216NWA一体机连接WiFi方法&#xff1a; 1、首先按打印机操作面板上的“功能键”&#xff1b;【用“”&#xff08;上翻页&#xff09;“-”&#xff08;下翻页&#xff09;来选择菜单的内容】 2、下翻页键找到并选择“网络”&#xff0c;然后“确认键”&#xff1b; 3…

YOLOV7改进实操-添加Wise IoU,实现有效提点

1、打开utils->general.py&#xff0c;找到bbox_iou&#xff08;&#xff09;&#xff0c;345行左右&#xff0c;将下面的与源码进行替换 wiou有三个版本&#xff0c;可以替换&#xff0c;看看哪一个提点多 class WIoU_Scale: monotonous: {None: origin v1True: monotoni…

【Unet系列】

https://tianfeng.space/1947.html 前言概念 图像分割 分割任务就是在原始图像中逐像素的找到你需要的家伙! 语义分割 就是把每个像素都打上标签&#xff08;这个像素点是人&#xff0c;树&#xff0c;背景等&#xff09; &#xff08;语义分割只区分类别&#xff0c;不区…

MySQL:温备份和恢复-mysqldump (4)

介绍 温备&#xff1a;同样是在数据库运行的时候进行备份的&#xff0c;但对当前数据库的操作会产生影响。&#xff08;只可以读操作&#xff0c;不可以写操作&#xff09; 温备份的优点&#xff1a; 1.可在表空间或数据文件级备份&#xff0c;备份时间短。 2.备份时数据库依然…

十四天学会C++之第一天(入门和基本语法)

C的起源和历史 C诞生于20世纪80年代初&#xff0c;它的创造者是计算机科学家Bjarne Stroustrup。当时&#xff0c;Stroustrup在贝尔实验室工作&#xff0c;他希望为C语言添加一些功能&#xff0c;以便更好地支持系统开发。这个愿望促使他创建了C。 C的名字来源于它的基因&…

Mongodb学习

一、初步了解 1.1 Mongodb 是什么 MongoDB 是一个基于分布式文件存储的数据库&#xff0c;官方地址 https://www.mongodb.com/ 1.2 数据库是什么 数据库&#xff08;DataBase&#xff09;是按照数据结构来组织、存储和管理数据的 应用程序 1.3 数据库的作用 数据库的主要…

微服务技术栈-初识Docker

文章目录 前言一、Docker概念二、安装Docker三、Docker服务命令四、Docker镜像和容器Docker镜像相关命令Docker容器相关命令 总结 前言 docker技术风靡全球&#xff0c;它的功能就是将linux容器中的应用代码打包,可以轻松的在服务器之间进行迁移。docker运行程序的过程就是去仓…

深入浅出,SpringBoot整合Quartz实现定时任务与Redis健康检测(一)

目录 前言 环境配置 Quartz 什么是Quartz&#xff1f; 应用场景 核心组件 Job JobDetail Trigger CronTrigger SimpleTrigger Scheduler 任务存储 RAM JDBC 导入依赖 定时任务 销量统计 Redis检测 使用 注意事项 前言 在悦享校园1.0中引入了Quartz框架实现…