网站搭建 | 部署
前一节已经规划好网站的的部署架构,现在开始逐一部署。

服务器
先从服务器开始,部署完之后再配置CDN然后DNS解析域名到CDN。
1Panel
1Panel 是新一代的 Linux 服务器运维管理面板
官网:https://1panel.cn

1Panel 在本地用了大半年了,UI现代清爽,主要是使用容器管理功能
勾选启动、停止、删除容器

追踪实时日志

进入终端

配置好服务器地址(支持IP和域名)后,点击端口能直接跳转

这几个功能直接在浏览器可视化操作,无需在服务器上手动输入命令,大大提升了项目部署的便利性。
OpenResty/Nginx
原本是打算自己部署Nginx容器手动配置的,但是后面发现1Panel 带有一些简单的WAF功能,就尝试一下

部署
直接在应用商店安装即可,1Panel 会自动按照默认配置创建容器。

默认的docker-compose内容:
services:
openresty:
image: 1panel/openresty:1.21.4.3-3-3-focal
container_name: ${CONTAINER_NAME}
restart: always
network_mode: host
volumes:
- ./conf/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf
- ./conf/fastcgi_params:/usr/local/openresty/nginx/conf/fastcgi_params
- ./conf/fastcgi-php.conf:/usr/local/openresty/nginx/conf/fastcgi-php.conf
- ./log:/var/log/nginx
- ./conf/conf.d:/usr/local/openresty/nginx/conf/conf.d/
- ./www:/www
- ./root:/usr/share/nginx/html
- /etc/localtime:/etc/localtime
- ./1pwaf/data:/usr/local/openresty/1pwaf/data
labels:
createdBy: "Apps"network_mode: host
容器与宿主机机共享相同的网络接口和IP地址,容器内的服务将直接通过主机的网络接口对外通信,而不是通过Docker分配的虚拟网络。
后续部署的服务要映射到宿主机端口,这样OpenResty才能反向代理到服务
安装完成后可以把之前申请的证书导入以备用或者在此处申请证书

主页 Home
官方项目地址:https://github.com/imsyy/home
未来子网站可能不止博客,为了方便导航就找了个人主页项目修改成自己的信息后放在主站页面上。

部署
打包构建镜像
把修改后的代码上传到服务器
# tree -L 1 -a
.
├── auto-imports.d.ts
├── CODE_OF_CONDUCT.md
├── components.d.ts
├── deploy.sh
├── docker-compose.yml
├── Dockerfile
├── .dockerignore
├── .env
├── .env.example
├── .eslintignore
├── .eslintrc.json
├── .git
├── .gitignore
├── .hintrc
├── index.html
├── LICENSE
├── package.json
├── pnpm-lock.yaml
├── .prettierrc.json
├── public
├── README_EN.md
├── README.md
├── screenshots
├── src
├── vite.config.js
└── .vscodeDockerfile
# 从node:18基础镜像创建一个名为builder的阶段,用于构建应用
FROM node:18 AS builder
# 设置工作目录为/app
WORKDIR /app
# 复制package*.json文件到工作目录
COPY package*.json ./
# 设置npm使用淘宝源 pnpm安装依赖
RUN npm config set registry https://registry.npmmirror.com && npm install -g pnpm && pnpm install
# 复制项目文件到工作目录
COPY . .
# 如果没有.env文件,则从.env.example复制一份作为.env文件,否则不做操作
RUN [ ! -e ".env" ] && cp .env.example .env || true
# 运行npm脚本进行构建
RUN pnpm build
# 从node:18-alpine基础镜像创建一个用于运行应用的最小化镜像
FROM node:18-alpine
# 设置工作目录为/app
WORKDIR /app
# 从builder阶段复制/dist目录到当前工作目录
COPY --from=builder /app/dist ./dist
# 同样设置npm使用淘宝源
RUN npm config set registry https://registry.npmmirror.com
# 全局安装http-server
RUN npm install -g http-server
# 暴露12445端口供外部访问
EXPOSE 12445
# 容器启动时运行http-server命令,使用dist目录作为静态文件目录,并指定端口为12445
CMD ["http-server", "dist", "-p", "12445"]docker-compose.yml
services:
icurvestar-home:
build:
context: .
dockerfile: Dockerfile
image: icurvestar-home:{datetime}
container_name: icurvestar-home
ports:
- "127.0.0.1:12445:12445"
networks:
- icurvestar_net
networks:
icurvestar_net:
name: icurvestar_net
driver: bridgedeploy.sh
#!/bin/bash
# 丢弃所有未提交的更改
git checkout .
# 拉取新代码
git pull
# 替换打包镜像的时间
current_datetime=$(date +'%Y-%m-%d-%H%M')
sed -i "s/{datetime}/${current_datetime}/g" docker-compose.yml
# 打包并运行
docker compose up --build -d# 执行deploy.sh脚本自动拉取最新代码、打包构建镜像、启动容器
bash deploy.sh配置OpenResty
创建网站
选择反向代理

配置SSL证书
选择上面导入好的证书

配置www子域名
我的网站是以icurvestar.cn为主站,www.icurvestar.cn重定向到icurvestar.cn
创建网站
重定向不做其他操作,选择静态网站类型

配置重定向
在www.icurvestar.cn添加一条重定向配置

效果:

博客 Blog
项目:VuePress Theme Hope - 一个具有强大功能的 vuepress 主题
VuePress 是以 Markdown 为中心的,项目中的每一个 Markdown 文件都是一个单独的页面,默认情况下,页面的路由路径是根据你的 Markdown 文件的相对路径决定的。
最初接触到VuePress Theme Hope这一主题的博客时,便对其文档型风格和主题设计产生了好感。能够将本地的Markdown文档直接转换为网页,无需后端编辑,操作便捷,决定采用这个主题。
└─ src
├─ demo
│ ├─ ...
│ └─ page.md
│ └─ markdown.md
│ └─ README.md
├─ ...
└─ README.mdMarkdown 文件对应的路由路径为:
| 相对路径 | 路由路径 |
|---|---|
/README.md | / |
/demo/README.md | /demo/ |
/demo/page.md | /demo/page.html |

部署
打包构建镜像
把修改后的代码上传到服务器
# tree -L 1 -a
.
├── deploy.sh
├── docker-compose.yml
├── Dockerfile
├── .dockerignore
├── .git
├── .gitignore
├── package.json
├── package-lock.json
├── src
└── tsconfig.jsonDockerfile
# 构建应用
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
# 设置npm使用淘宝源 pnpm安装依赖
RUN npm config set registry https://registry.npmmirror.com && npm install
# 修改node_modules中的代码,替换cdn地址
RUN sed -i 's/cdn.jsdelivr.net/jsd.onmicrosoft.cn/g' ./node_modules/vuepress-plugin-components/lib/node/index.js
COPY . .
RUN npm run docs:build
# 最小化镜像
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/src/.vuepress/dist ./dist
# 同样设置npm使用淘宝源
RUN npm config set registry https://registry.npmmirror.com
RUN npm install -g http-server
EXPOSE 8080
CMD ["http-server", "dist", "-p", "8080"]docker-compose.yml
services:
icurvestar-blog:
build:
context: .
dockerfile: Dockerfile
image: icurvestar-blog:{datetime}
container_name: icurvestar-blog
ports:
- "127.0.0.1:18080:8080"
networks:
- icurvestar_net
networks:
icurvestar_net:
name: icurvestar_net
driver: bridgedeploy.sh
#!/bin/bash
# 丢弃所有未提交的更改
git checkout .
# 拉取新代码
git pull
# 替换打包镜像的时间
current_datetime=$(date +'%Y-%m-%d-%H%M')
sed -i "s/{datetime}/${current_datetime}/g" docker-compose.yml
# 打包并运行
docker compose up --build -d配置OpenResty
创建网站
参照主页的配置,一样选择反向代理

配置SSL证书

CDN
又拍云有又拍云联盟开发者帮助计划,之前在其他地方也看到过,所以CDN平台选择又拍云,看看效果如何。
新建服务
又拍云CDN操作台创建 CDN 服务

需要创建3个服务,分别加速icurvestar.cn, www.icurvestar.cn, blog.icurvestar.cn这3个域名
域名绑定
选择通过 DNS 解析验证

根据提示的解析记录到阿里云DNS控制台添加解析记录

完成后删除解析记录
添加SSL证书
如果是椭圆曲线(Elliptic Curve, EC)私钥 私钥的开始标题和结尾标题,都需要加上 EC 指示,例如: 从: -----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY----- 改为: -----BEGIN EC PRIVATE KEY-----
-----END EC PRIVATE KEY-----


访问频率限制
根据具体网页实际情况限制

解析DNS
到阿里云DNS控制台添加又拍云提供的CNAME解析记录。
在又拍云创建3个服务,所以也需要添加3条对应icurvestar.cn, www.icurvestar.cn, blog.icurvestar.cn这3个域名的CNAME解析记录。

防止源站IP泄漏

使用Nginx作为Web服务器时,若遇到未绑定的域名解析错误,可能会导致访问请求被错误地导向其他站点,存在恶意解析风险。当直接访问443端口时,Nginx会默认使用首个配置了SSL证书的站点证书来建立连接,这无疑会暴露服务器的信息。为防止此类情况发生可以通过为默认站点配置一个空白证书的方式来妥善解决这一问题。
使用1Panel创建网站后访问IP并未发现此问题,保险起见还是做一下
# 生成2048位的RSA私钥并保存为server.key文件
openssl genrsa -out blank.key 2048
# 使用私钥创建一个新的证书签名请求并保存为server.csr文件
openssl req -new -key blank.key -out blank.csr -subj "/"
# 根据证书签名请求生成有效期为100年的自签名证书并保存为server.crt文件
openssl x509 -req -days 36500 -in blank.csr -signkey blank.key -out blank.crt在 Nginx 中,批量载入配置文件(例如通过 include /path/to/conf.d/*.conf)时,Nginx 会按照 ASCII 顺序加载这些配置文件。比如配置文件命名为 server_a.conf、server_b.conf、server_c.conf,它们就会以这个顺序加载。
Nginx 的默认服务器(default_server)用于处理未明确指定主机名(域名)或 IP 的请求。如果在这些配置文件中没有显式声明 default_server,那么第一个含有SSL证书的server 块会默认处理这些请求。
如果想指定某个 server 块为默认服务器,需要在该 server 块的 listen 指令中添加 default_server 参数。例如:
nginx复制代码server {
listen 80 default_server;
server_name _;
# 其他配置...
}这样,无论加载顺序如何,包含 default_server 的 server 块将始终作为默认服务器来处理未绑定域名/IP 的请求。
手动配置:
ip.conf
server
{
listen 80 default_server;
server_name _;
location / {
return 444;
}
}
server
{
listen 443 ssl default_server;
server_name _;
ssl_certificate /etc/nginx/ssl/blank.crt;
ssl_certificate_key /etc/nginx/ssl/blank.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
ssl_session_timeout 10m;
location / {
return 444;
}
}OpenResty创建网站
选择静态网站类型

配置空白SSL证书
