- 一、整体架构
- 二、第一步:服务器基础环境
- 三、第二步:构建 Vue3 镜像
- 四、第三步:宿主机 Nginx 做 HTTPS 卸载
- 五、第四步:Let’s Encrypt 免费证书 + 自动续期
- 六、第五步:接上 CI/CD 自动发布
- 七、总结:这份部署清单的含金量
上一篇《前端工程化与 CI/CD 落地实践》里,我讲了 GitHub Actions 怎么把”代码 → 镜像 → 服务器”串起来。这篇回答大家问得最多的一个问题:“我有了一台服务器、一个域名,具体怎么把 Vue 项目真正跑起来、带 HTTPS 那种?” 本文用一台 CentOS 服务器为例,跑通完整链路。
一、整体架构
用户浏览器
│ https://blog.shanky.cn
▼
Nginx(宿主 443/80 端口,容器内对外唯一入口)
├── 443 HTTPS + HTTP/2 → 反代到 Vue 静态容器(8080)
└── 80 HTTP → 301 跳转 HTTPS(配合 certbot 签发/续期)
│
▼
Vue3 前端容器(Nginx 托管 dist,SPA 路由回退)
核心思路:Vue 的 dist 用 Nginx 容器托管,宿主机的 Nginx 只做”HTTPS 卸载 + 反代”。这样前端容器可以随时重建、换版本,证书和路由规则都收在宿主机一层,职责清晰。
二、第一步:服务器基础环境
# 1. 安装 Docker(CentOS 7+,方法同我之前写的《Centos 安装 docker-compose》前置)
curl -fsSL https://get.docker.com | bash -s docker
systemctl enable --now docker
# 2. 安装 docker-compose 插件(可选,多容器编排更方便)
yum install -y docker-compose-plugin
# 3. 放行端口(云厂商安全组 + 本机 firewalld 都要放)
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
新手最常踩的坑:云厂商安全组和系统防火墙是两套东西,都要放行 80/443,否则从外网永远打不开,但本机 curl 却正常。
三、第二步:构建 Vue3 镜像
前端项目结构(接上一篇的 CI/CD 工程):
# Dockerfile —— 多阶段构建
# 阶段1:node 构建(带缓存优化,package-lock 不变就不重装依赖)
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 阶段2:nginx 托管静态产物
FROM nginx:1.27-alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
# nginx.conf —— 容器内配置:SPA 回退 + gzip + 静态资源长缓存
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
gzip on;
gzip_types text/plain text/css application/javascript application/json image/svg+xml;
location / {
try_files $uri $uri/ /index.html; # SPA 路由回退
}
location /assets/ {
expires 30d;
add_header Cache-Control "public, immutable";
}
}
本地构建并起容器验证:
docker build -t my-vue-app:1.0.0 .
# 先在本机 8080 验证,容器内映射到 80
docker run -d --name my-vue-app -p 8080:80 my-vue-app:1.0.0
curl http://localhost:8080 # 能返回 index.html 即成功
SPA 路由回退(
try_files ... /index.html)的坑我早在《vue-cli 项目在 nginx 下子页面刷新404》写过,忘了的回去复习:刷新/about时 Nginx 找不到对应文件,必须回退到index.html交给前端路由。
四、第三步:宿主机 Nginx 做 HTTPS 卸载
前端容器跑在 8080,但用户只认 443。在宿主机装 Nginx,做HTTPS 终结 + 反代:
yum install -y nginx
# /etc/nginx/conf.d/vue-app.conf
server {
listen 443 ssl http2;
server_name blog.shanky.cn;
# 证书路径(certbot 生成,见下节)
ssl_certificate /etc/letsencrypt/live/blog.shanky.cn/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/blog.shanky.cn/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# 反代到 Vue 容器
location / {
proxy_pass http://127.0.0.1:8080;
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_set_header X-Forwarded-Proto $scheme;
}
}
# 80 端口统一跳 HTTPS(顺便让 certbot 的验证请求通过)
server {
listen 80;
server_name blog.shanky.cn;
location /.well-known/acme-challenge/ { root /var/www/certbot; }
location / { return 301 https://$host$request_uri; }
}
为什么用”宿主机 Nginx + 容器内 Nginx”两层?一层职责是证书/反代/跳转,一层职责是托管静态资源。你也可以用一个 Nginx 容器把两个职责合并,但单独一层宿主机 Nginx 在以后挂多个站点、多个后端时更灵活——这也是”前端也要懂点服务器”的价值所在。
五、第四步:Let’s Encrypt 免费证书 + 自动续期
用 certbot 签发免费 HTTPS 证书:
yum install -y certbot python3-certbot-nginx
# 非交互签发(nginx 插件会自动改配置,但我们已经手写了 conf,用 webroot 方式更稳)
certbot certonly --webroot -w /var/www/certbot \
-d blog.shanky.cn \
--email your@email.com --agree-tos --no-eff-email
证书有效期 90 天,必须自动续期。加定时任务:
# 每月1号凌晨 3 点续期 + 重载 nginx
echo "0 3 1 * * root certbot renew --quiet && systemctl reload nginx" >> /etc/crontab
线上 HTTPS 最关键的不是”怎么签”,而是”怎么续”。很多站点证书过期打不开,就是因为只配了签发、忘了配自动续期。
certbot renew只会对距到期不足 30 天的证书真正续期,平时运行几乎零开销,放心挂 cron。
六、第五步:接上 CI/CD 自动发布
有了容器化基础,接上一篇的 GitHub Actions 就水到渠成:CI 里 docker build 打镜像推送到镜像仓库,CD 阶段 SSH 到服务器 docker pull + docker run。
# .github/workflows/deploy.yml 的关键步骤
- name: 服务器部署
uses: appleboy/ssh-action@v1
with:
host: $
username: root
key: $
script: |
docker pull my-vue-app:$
docker stop my-vue-app || true
docker rm my-vue-app || true
docker run -d --name my-vue-app -p 8080:80 my-vue-app:$
# 服务器上验证 8080 容器 + 443 外层是否都正常
curl -sI https://blog.shanky.cn | head -n 5
# HTTP/2 200 ✔
到这里,你从”写代码”到”上线”只需要一次
git push:CI 自动 lint/测试/构建/打镜像,CD 自动部署,HTTPS 证书每月自动续期。这就是上一篇说的全链路闭环,也是前端工程师最有含金量的加分项。
七、总结:这份部署清单的含金量
把这条链路完整跑通并讲清楚,面试时你就能说出别人说不出的细节:
- 安全组 vs 防火墙:两套放行机制,缺一不可;
- 多阶段构建:为什么 node 构建产物只需要 nginx 一个运行时,镜像能瘦多少(
docker images对比一下); - HTTPS 卸载:为什么证书要放宿主 Nginx 而不是 Vue 容器里;
- 自动续期:
certbot renew+ cron,运维意识落地; - 全自动发布:一次
git push直达线上,版本可回滚(回滚方法见上一篇)。
一句话总结:”我用 Docker 多阶段构建打包 Vue3 产物,宿主机 Nginx 做 HTTPS 终结和反向代理,certbot 自动续期证书,CI/CD 一键发布到服务器,整个部署链路是自动化的、可回滚的。”
这篇文章和《前端工程化与 CI/CD》《Centos 安装 docker-compose》《Nginx 负载均衡》《vue-cli 项目在 nginx 下子页面刷新404》一起,构成了”前端从开发到上线的完整知识闭环”。下一篇我会把这个博客本身容器化,讲讲静态站如何用 Docker 跑出构建缓存和自动发布。
