GitHub Actions 自动化运维实战:TypeScript 全栈项目 CI/CD 至腾讯云(生产级指南)
GitHub Actions 自动化运维实战TypeScript 全栈项目 CI/CD 至腾讯云生产级指南摘要本文手把手教你构建一套基于GitHub Actions的自动化运维体系实现TypeScript 全栈项目Node.js React/Vue从代码提交到腾讯云服务器的全自动 CI/CD 流程。涵盖 Docker 多阶段构建、腾讯云容器镜像服务CCR推送、SSH 免密部署及 Nginx 反向代理等核心实战技巧所有配置均经过生产环境验证可直接复用。一、为什么选择 GitHub Actions 腾讯云在 DevOps 实践中全栈 TypeScript 项目如 NestJS React/Vue的部署常面临环境不一致、构建慢、发布繁琐等问题。本方案具有以下核心优势核心优势详细说明国内访问极速利用腾讯云容器镜像服务 (CCR)作为私有镜像仓库告别 Docker Hub 在国内拉取超时的痛点。全流程自动化从git push到生产环境上线无需人工干预消除人为操作失误。环境一致性基于Docker 多阶段构建保证开发、测试、生产环境 100% 一致。成本优化利用 GitHub Actions 的免费额度私有库每月 2000 分钟和腾讯云轻量服务器性价比极高。适用场景个人开发者、中小团队、创业公司快速搭建标准化部署流程。二、部署架构与核心原理2.1 整体架构图开发者提交代码 (Git Push) │ ▼ ┌───────────────────────────┐ │ GitHub Repository │ │ (触发 Workflow 监听 Main) │ └───────────┬───────────────┘ ▼ ┌───────────────────────────┐ │ GitHub Actions Runner │ │ (Ubuntu 最新版虚拟机) │ │ 1. 检出代码 │ │ 2. Node.js 环境配置 │ │ 3. 前端 pnpm build │ │ 4. 后端 tsc 编译 │ │ 5. Docker 镜像构建 │ │ 6. 推送至腾讯云 CCR │ └───────────┬───────────────┘ ▼ ┌───────────────────────────┐ │ 腾讯云容器镜像服务 (CCR) │ │ ccr.ccs.tencentyun.com │ └───────────┬───────────────┘ ▼ ┌───────────────────────────┐ │ 腾讯云服务器 (CVM/Lighthouse)│ │ 1. SSH 登录 │ │ 2. Docker Login (CCR) │ │ 3. Docker Compose 更新 │ │ 4. Nginx 反向代理 │ └───────────┬───────────────┘ ▼ 用户访问 (80/443)2.2 技术栈选型前端TypeScript React/Vue 3 Vite后端TypeScript Node.js (NestJS/Express/Koa)容器化Docker Docker ComposeCI/CDGitHub Actions云服务腾讯云轻量应用服务器 / CVM 容器镜像服务 (CCR)三、腾讯云环境准备关键步骤3.1 开通腾讯云容器镜像服务 (CCR)注意登录凭证并非腾讯云官网密码而是控制台生成的访问凭证。进入腾讯云控制台 →容器镜像服务选择实例列表→个人版免费创建命名空间如my-ts-project创建镜像仓库如fullstack-app获取登录凭证进入访问凭证页面点击生成临时登录指令或设置固定密码记录用户名通常是1000xxxx即主账号 ID和密码3.2 配置腾讯云服务器 (Ubuntu 22.04)避坑指南新购 Ubuntu 22.04 实例默认禁用 root 密码登录且需配置 Docker 权限。# 1. 使用 ubuntu 用户登录默认用户sshubuntu你的服务器公网IP# 2. 安装 Docker 和 Docker Compose 插件sudoaptupdatesudoaptinstall-ydocker.io docker-compose-plugin# 3. 将当前用户加入 docker 组解决权限问题无需每次 sudosudousermod-aGdocker$USER# 4. 刷新组权限重要否则不生效newgrpdocker# 5. 验证安装dockerpsdockercompose version3.3 配置 SSH 部署密钥为了安全我们生成一对专用密钥用于 GitHub Actions 登录。# 在本地机器生成密钥不要设置密码ssh-keygen-mPEM-trsa-b4096-f~/.ssh/github-tencent-deploy-Cgithub-actions# 将公钥拷贝到服务器ssh-copy-id-i~/.ssh/github-tencent-deploy.pub ubuntu你的服务器公网IP# 测试连接ssh-i~/.ssh/github-tencent-deploy ubuntu你的服务器公网IP四、项目配置与 Docker 优化4.1 推荐的项目结构 (Monorepo). ├── .github/workflows/deploy.yml # GitHub Actions 配置 ├── server/ # Node.js 后端 │ ├── src/ │ ├── package.json │ └── tsconfig.json ├── web/ # React/Vue 前端 │ ├── src/ │ ├── dist/ # 构建产物 │ ├── package.json │ └── nginx.conf # Nginx 配置 ├── docker-compose.yml └── Dockerfile # 多阶段构建文件4.2 多阶段构建 Dockerfile (核心)优化点利用 Docker 层缓存机制大幅加速 CI/CD 构建速度。# 阶段 1: 构建前端 FROM node:18-alpine AS web-build WORKDIR /web COPY web/package*.json ./ # 使用 pnpm 加速依赖安装 RUN npm install -g pnpm pnpm install COPY web/ . RUN pnpm run build # 阶段 2: 构建后端 FROM node:18-alpine AS server-build WORKDIR /server COPY server/package*.json ./ RUN npm install COPY server/ . # 仅编译 TS不运行测试 RUN npm run build # 阶段 3: 生产环境 FROM node:18-alpine # 安装 Nginx (用于托管前端静态资源和反向代理) RUN apk add --no-cache nginx WORKDIR /app # 1. 拷贝后端产物 COPY --fromserver-build /server/dist ./dist COPY --fromserver-build /server/node_modules ./node_modules COPY --fromserver-build /server/package.json ./ # 2. 拷贝前端产物到 Nginx 目录 COPY --fromweb-build /web/dist /usr/share/nginx/html # 3. 配置 Nginx COPY web/nginx.conf /etc/nginx/http.d/default.conf # 4. 暴露端口 EXPOSE 80 3000 # 5. 启动脚本同时启动 Node 服务和 Nginx RUN echo #!/bin/sh /start.sh \ echo nginx -g daemon off; /start.sh \ echo node dist/main.js /start.sh \ chmod x /start.sh CMD [/start.sh]4.3 Nginx 配置 (web/nginx.conf)解决前端路由刷新 404 和 API 代理问题。server { listen 80; server_name localhost; # 前端静态资源 location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html; # 解决 SPA 路由问题 } # 后端 API 代理 location /api/ { proxy_pass http://localhost:3000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }五、GitHub Actions 全流程配置 (CI/CD)5.1 配置 GitHub Secrets在 GitHub 仓库Settings - Secrets and variables - Actions中添加以下密钥Secret 名称描述获取来源TENCENT_CCR_USERNAME腾讯云镜像仓库用户名容器镜像服务 - 访问凭证TENCENT_CCR_PASSWORD腾讯云镜像仓库密码容器镜像服务 - 访问凭证SERVER_HOST腾讯云服务器公网 IP腾讯云控制台SERVER_USER服务器登录用户推荐填ubuntuSSH_PRIVATE_KEYSSH 私钥内容~/.ssh/github-tencent-deploy文件内容SERVER_PORTSSH 端口默认22(可选)5.2 Workflow 配置文件 (.github/workflows/deploy.yml)这是本文最核心的部分已修正所有常见错误。name:TS Fullstack CI/CD to Tencent Cloudon:push:branches:[main]# 仅监听 main 分支的 push 事件workflow_dispatch:# 支持手动触发jobs:build-and-push:runs-on:ubuntu-lateststeps:-name:1. 检出代码uses:actions/checkoutv4-name:2. 设置 Docker Buildx (开启缓存)uses:docker/setup-buildx-actionv3-name:3. 登录腾讯云容器镜像服务uses:docker/login-actionv3with:registry:ccr.ccs.tencentyun.comusername:${{secrets.TENCENT_CCR_USERNAME}}password:${{secrets.TENCENT_CCR_PASSWORD}}-name:4. 提取 Git Commit SHA (用于镜像标签)id:metarun:echo sha_short$(git rev-parse--short HEAD)$GITHUB_OUTPUT-name:5. 构建并推送 Docker 镜像uses:docker/build-push-actionv5with:context:.file:./Dockerfilepush:trueplatforms:linux/amd64# 腾讯云轻量服务器通常是 amd64 架构tags:|ccr.ccs.tencentyun.com/my-ts-project/fullstack-app:${{ steps.meta.outputs.sha_short }} ccr.ccs.tencentyun.com/my-ts-project/fullstack-app:latestcache-from:typegha# 使用 GitHub Actions 缓存cache-to:typegha,modemaxdeploy:needs:build-and-push# 等待构建任务成功后再执行runs-on:ubuntu-lateststeps:-name:1. SSH 登录服务器并执行部署uses:appleboy/ssh-actionv1.0.0with:host:${{secrets.SERVER_HOST}}username:${{secrets.SERVER_USER}}key:${{secrets.SSH_PRIVATE_KEY}}port:${{secrets.SERVER_PORT||22}}script:|set -e # 遇到错误立即退出防止错误状态继续运行echo 开始部署到腾讯云服务器...# 登录腾讯云镜像仓库docker login ccr.ccs.tencentyun.com \-u ${{secrets.TENCENT_CCR_USERNAME}}\-p ${{secrets.TENCENT_CCR_PASSWORD}}# 进入项目目录mkdir-p /opt/ts-fullstack cd /opt/ts-fullstack# 写入 .env 文件供 docker-compose 使用echo IMAGEccr.ccs.tencentyun.com/my-ts-project/fullstack-app:latest.env# 拉取最新镜像docker compose pull app||docker-compose pull app# 停止旧容器启动新容器docker compose down||docker-compose down docker compose up-d||docker-compose up-d# 清理 24 小时前未被使用的镜像释放磁盘空间docker image prune-af--filter until24h echo ✅ 部署成功访问 http://${{secrets.SERVER_HOST}}查看效果5.3 服务器端 Docker Compose 配置在服务器/opt/ts-fullstack/目录下创建docker-compose.ymlversion:3.8services:app:image:${IMAGE:-ccr.ccs.tencentyun.com/my-ts-project/fullstack-app:latest}container_name:ts_fullstack_apprestart:alwaysports:-80:80# Nginx 端口# - 3000:3000 # 无需暴露后端端口由 Nginx 反向代理environment:-NODE_ENVproductionvolumes:-/data/logs:/app/logs# 挂载日志目录healthcheck:test:[CMD,curl,-f,http://localhost:80]interval:30stimeout:10sretries:3六、常见问题排查 (Troubleshooting)问题现象原因分析解决方案SSH 连接失败腾讯云新实例安全组未放行 22 端口或使用了 root 用户登录。检查安全组规则使用ubuntu用户 密钥认证。Permission denied (publickey)私钥格式错误或公钥未加入authorized_keys。确保私钥是 PEM 格式 (-m PEM)检查服务器~/.ssh/authorized_keys权限是否为600。镜像推送 401 Unauthorized使用了腾讯云官网登录密码而非 CCR 访问凭证密码。前往容器镜像服务 - 访问凭证重新生成密码并更新 GitHub Secrets。Docker 命令权限不足用户未加入docker组。执行sudo usermod -aG docker $USER并重新登录 SSH。前端刷新 404Nginx 未配置 SPA 路由回退。检查nginx.conf中location /块是否包含try_files $uri $uri/ /index.html;。七、总结与最佳实践通过本文的配置你已经拥有了一套生产级、高可用、自动化的 TypeScript 全栈部署方案。核心价值效率提升代码提交即发布将部署时间从 30 分钟缩短至 5 分钟以内。质量保障Docker 镜像固化环境消除“在我机器上能跑”的问题。安全可靠密钥加密存储服务器无硬编码密码支持快速回滚通过 Git Tag。进阶建议多环境部署利用 Git Tag (v1.0.0) 触发生产环境部署利用 Branch (dev) 触发测试环境部署。监控告警集成钉钉/企业微信机器人在部署成功或失败时发送通知。数据库迁移在ssh-action中添加npx prisma migrate deploy或typeorm migration:run步骤。互动话题你在部署 TypeScript 全栈项目时遇到过哪些棘手问题是 Docker 构建缓存失效还是 Nginx 反向代理配置错误欢迎在评论区交流讨论