虚拟机上实现最简 CI/CD

手把手在 CentOS 7 虚拟机上实现最简 CI/CD(无 Docker / 无云服务)

本文通过纯本地环境(CentOS 7 + Git + Apache)演示 CI/CD 核心流程,帮助初学者理解持续集成与持续部署的本质。


📚 目录(点击跳转)


为什么要在本地实现 CI/CD?

  • 理解 CI/CD 的底层原理
  • 不依赖 GitHub/GitLab/Jenkins 等外部平台
  • 适合学习、实验和内网开发环境

完整流程图:

开发者本地

│ git add / commit / push

Bare 仓库:/opt/git/myapp.git\] ← 模拟 GitHub │ │ 触发 post-receive 钩子 ▼ \[CI/CD 脚本执行

├─ 1. 临时目录检出最新代码(/tmp/...)

├─ 2. 运行测试(如检查 index.html 是否存在)← CI

└─ 3. 同步文件到 /var/www/html/myapp/ ← CD

Apache Web 服务\] ← 用户访问的"生产环境" [↑ 回到顶部](#↑ 回到顶部) *** ** * ** *** ### 一、实验环境准备 * 操作系统:CentOS 7 虚拟机 * 所需软件:git、python3(可选)、httpd(Apache) * 网络要求:仅本地回环,无需外网 [↑ 回到顶部](#↑ 回到顶部) *** ** * ** *** ### 二、创建本地"远程" Git 仓库 * 使用 `git init --bare` 模拟远程仓库 * 仓库路径示例:`/opt/git/myapp.git` #清理旧环境(确保干净起点) rm -rf ~/myapp-dev /opt/git/myapp.git /var/www/html/myapp /tmp/myapp-deploy-* systemctl restart httpd #创建"内部 GitHub"(bare 仓库) mkdir -p /opt/git/myapp.git cd /opt/git/myapp.git git init --bare #配置 Git 用户(避免提交报错) #这里可以不是真实的用户名和邮箱,只是为了区分git用户避免混杂 git config --global user.name "ci-cd" git config --global user.email "ci-cd@example.com" [↑ 回到顶部](#↑ 回到顶部) *** ** * ** *** ### 三、开发者工作目录初始化 * 克隆 bare 仓库到本地开发目录 * 创建简单应用(如 `index.html`) * 首次提交并推送至"远程" #创建开发目录并首次提交 cd ~ git clone /opt/git/myapp.git myapp-dev cd myapp-dev echo '

CI/CD Works!

' > index.html git checkout -b main # 显式创建 main 分支 git add . git commit -m "Initial commit" git push origin main # 首次推送 安装 rsync(用于同步文件)---这个得安装好 yum install -y rsync [↑ 回到顶部](#↑ 回到顶部) *** ** * ** *** ### 四、核心:配置 Git Hook 实现自动化(CI/CD 关键) * 编写 `post-receive` 钩子脚本 * 实现两个阶段: * **CI(持续集成)**:代码检出 + 基础校验(如文件存在性) * **CD(持续部署)**:自动同步到 Web 目录 #### post-receive 钩子脚本 cat > /opt/git/myapp.git/hooks/post-receive << 'EOF' #!/bin/bash # 启用严格模式:任何命令失败立即退出 set -e # 部署目标目录(Apache 会从此处提供网页) DEPLOY_DIR="/var/www/html/myapp" # 临时工作目录(每次部署都新建,避免残留) TMP_DIR="/tmp/myapp-deploy-$$" # $$ 是当前进程 ID,保证唯一 # ================================ # 第一步:获取 Git 推送的新提交 ID # ================================ # Git 在 post-receive 中会通过标准输入(stdin)传入一行: # # 例如:000... dcc19ac refs/heads/main read oldrev newrev refname # 如果是删除分支(newrev 全 0),直接退出 if [ "$newrev" = "0000000000000000000000000000000000000000" ]; then exit 0 fi # ================================ # 第二步:清理并准备临时目录 # ================================ rm -rf "$TMP_DIR" mkdir -p "$TMP_DIR" # ================================ # 第三步:从 bare 仓库提取新代码(关键!) # ================================ # 使用 git archive + newrev 提取指定提交的内容 # 输出是 tar 流,直接 pipe 给 tar 解压到 TMP_DIR git --git-dir=/opt/git/myapp.git archive "$newrev" | tar -x -C "$TMP_DIR" # ================================ # 第四步:CI ------ 检查关键文件是否存在 # ================================ if [ ! -f "$TMP_DIR/index.html" ]; then echo " CI FAILED: index.html not found!" exit 1 # 部署中断 fi echo " CI PASSED: index.html is present." # ================================ # 第五步:CD ------ 部署到 Web 目录 # ================================ mkdir -p "$DEPLOY_DIR" # 同步 TMP_DIR/ 下所有内容到 DEPLOY_DIR/ # 注意结尾的 "/":表示同步内容,而不是嵌套目录 rsync -a --delete "$TMP_DIR/" "$DEPLOY_DIR/" # 设置 Apache 可读权限(CentOS 默认用户是 apache) chown -R apache:apache "$DEPLOY_DIR" chmod -R 755 "$DEPLOY_DIR" # 成功提示 echo " Deployed to http://localhost/myapp/" EOF ## 添加执行权限(必须!) chmod +x /opt/git/myapp.git/hooks/post-receive [↑ 回到顶部](#↑ 回到顶部) *** ** * ** *** ### 五、配置 Apache 支持部署访问 * 设置 Web 根目录权限 * 确保 Apache 可读取部署路径 * 访问测试:`http://localhost/myapp/` #测试部署 cd ~/myapp-dev echo '

Auto Deploy Success! v2

' > index.html git add . git commit -m "Test auto deploy" git push origin main ##你应该看到输出: remote: CI PASSED: index.html is present. remote: Deployed to http://localhost/myapp/ 验证: cat /var/www/html/myapp/index.html # 输出:

Auto Deploy Success! v2

浏览器访问:http://虚拟机IP/myapp/ [↑ 回到顶部](#↑ 回到顶部) *** ** * ** *** ### 六、完整流程测试 * 修改代码 → `git add/commit/push` * 观察钩子自动执行输出 * 验证网页内容是否自动更新 为了完成本地提交--》自动部署 --》网页更新,同时需要展示当前时间,但在html文件中,$(date)只是一个普通的字符串,它是bash的命令语法,所以需要在部署之前将当前时间替换上去(对post-receive脚本进行修改),具体修改如下 cat > /opt/git/myapp.git/hooks/post-receive << 'EOF' #!/bin/bash set -e DEPLOY_DIR="/var/www/html/myapp" TMP_DIR="/tmp/myapp-deploy-$$" read oldrev newrev refname if [ "$newrev" = "0000000000000000000000000000000000000000" ]; then exit 0 fi rm -rf "$TMP_DIR" mkdir -p "$TMP_DIR" # 提取新提交的内容 git --git-dir=/opt/git/myapp.git archive "$newrev" | tar -x -C "$TMP_DIR" # 检查 index.html 是否存在 if [ ! -f "$TMP_DIR/index.html" ]; then echo "CI FAILED: index.html not found!" exit 1 fi echo "CI PASSED: index.html is present." #关键:在部署前替换 $(date) 为真实时间 current_time=$(date '+%Y-%m-%d %H:%M:%S') sed -i "s/\$(date)/$current_time/" "$TMP_DIR/index.html" # 部署到 Web 目录 mkdir -p "$DEPLOY_DIR" rsync -a --delete "$TMP_DIR/" "$DEPLOY_DIR/" chown -R apache:apache "$DEPLOY_DIR" chmod -R 755 "$DEPLOY_DIR" echo "Deployed to http://localhost/myapp/" EOF chmod +x /opt/git/myapp.git/hooks/post-receive 然后进行如下操作: ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/3d579a0bb55842b4883c8036f461a71a.png) 测试 cd ~/myapp-dev echo '

CI/CD FULL TEST PASSED! $(date)

' > index.html git add . git commit -m "Test dynamic date" git push origin main http://192.168.126.50/myapp/ ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/e64e137846244b30a284743f557d2dd8.png) [↑ 回到顶部](#↑ 回到顶部) *** ** * ** *** ### 七、总结:我们实现了什么? | 步骤 | 对应 CI/CD 概念 | |----------------|-------------| | `git push` | 代码提交触发 | | `post-receive` | 自动化流水线 | | 文件校验 | 持续集成(CI) | | 同步到 Web 目录 | 持续部署(CD) | * 无需 Docker、无需云服务、100% 本地闭环 * 真正理解"提交即部署"的背后机制 [↑ 回到顶部](#↑ 回到顶部) *** ** * ** *** ### 八、后续可扩展方向(进阶) * 加入单元测试脚本(如 Python unittest) * 部署动态应用(如 Flask + systemd) * 使用 rsync 或 scp 实现多节点部署 * 添加邮件/日志通知机制 [↑ 回到顶部](#↑ 回到顶部) *** ** * ** *** > 提示:本文所有操作均在 CentOS 7 虚拟机中完成,适合零基础读者动手实践。 > > 如果你觉得有帮助,欢迎点赞、收藏、评论交流!

相关推荐
测试者家园13 小时前
DevOps 到底改变了测试什么?
运维·自动化测试·软件测试·devops·持续测试·智能化测试·软件测试和开发
青靴19 小时前
轻量级 CI/CD:Git Hooks 自动部署 Node.js 应用(CICD-demo)
git·ci/cd·node.js
青靴1 天前
轻量级 CI/CD 实战(四):本地开发钉钉告警 → 自动部署云服务器 Kafka 消费者容器
ci/cd·docker·钉钉
奔跑吧邓邓子1 天前
Jenkins自动化持续集成:从入门到实战
ci/cd·自动化·实战·jenkins·自动化持续集成
青靴2 天前
Git Hooks 实现 CI/CD 进阶实践 -- 根据实际需求添加功能
git·elasticsearch·ci/cd
t***L2662 天前
DevOps自动化部署
运维·自动化·devops
DreamLife☼2 天前
Docker-CI/CD:集成 GitHub Actions 实现自动化构建与部署
ci/cd·docker·自动化部署·github actions·镜像构建·trivy 扫描·compose 部署
西维2 天前
告别手动部署!Docker + Drone 前端自动化部署指南
前端·ci/cd·docker
g***B7383 天前
DevOps文化推广
运维·devops