网络主机上的自动化Git部署 — 初学者CI/CD指南

使用共享主机的开发者经常发现自己每次修改代码后都要手动通过FTP上传文件——既费时又容易出错。好消息是,支持SSH的主机可以配置为使用Git裸存储库和post-receive钩子每次git push时自动部署。本指南将介绍在DirectAdmin主机上的完整设置步骤。

前提条件:主机已启用SSH访问,本地已安装Git(用git --version检查),已有GitHub或GitLab存储库。

1. 什么是主机上的CI/CD?

CI/CD(持续集成/持续部署)自动化了将代码更改部署到线上服务器的过程。对于共享主机,实际方法是在服务器上使用Git裸存储库结合post-receive钩子——一个在代码推送时自动运行的Shell脚本。

流程是:从本地机器推送代码到主机服务器 → post-receive钩子自动运行git checkout → 更新的文件立即出现在public_html中。

2. 您需要什么

AsiaGB主机:通过提交包含您主机用户名的支持工单可以启用SSH访问。我们的团队将在24小时内激活。

3. 在服务器上创建Git裸存储库

通过SSH连接并在public_html之外创建裸存储库:

# Connect via SSH
ssh [email protected]

# Create a folder for the bare repo (outside public_html)
mkdir ~/repos
cd ~/repos
git init --bare mysite.git

裸存储库没有工作目录——它纯粹作为推送的接收端点,而不是存储可编辑文件的地方。

4. 创建post-receive钩子脚本

钩子脚本是Git在接收到推送后自动运行的Shell脚本。创建钩子文件:

nano ~/repos/mysite.git/hooks/post-receive

粘贴以下内容,将/home/username/public_html替换为您的实际路径:

#!/bin/bash
# post-receive hook — deploy to public_html
GIT_WORK_TREE=/home/username/public_html
export GIT_WORK_TREE

GIT_DIR=/home/username/repos/mysite.git
export GIT_DIR

git checkout -f main

echo "Deploy complete: $(date)"

保存文件,然后使其可执行:

chmod +x ~/repos/mysite.git/hooks/post-receive

⚠️ 检查您的分支名称:如果您的存储库使用master而不是main,请将git checkout -f main更改为git checkout -f master。

5. 在本地机器上添加远程

在您的本地项目目录中,将主机服务器添加为Git远程:

# Navigate to your local project
cd ~/myproject

# Add the hosting server as a remote named "hosting"
git remote add hosting ssh://[email protected]/home/username/repos/mysite.git

# Test with your first push
git push hosting main

如果一切配置正确,您将看到来自钩子的"Deploy complete"消息,您更新的文件将立即出现在public_html中。

6. GitHub/GitLab Webhook(高级)

要在每次推送到GitHub或GitLab时自动触发部署,请在public_html中创建PHP webhook接收器:

# Create deploy.php in public_html
<?php
$secret = 'YOUR_WEBHOOK_SECRET';
$payload = file_get_contents('php://input');
$sig = 'sha256=' . hash_hmac('sha256', $payload, $secret);

if (!hash_equals($sig, $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? '')) {
    http_response_code(403); exit;
}

exec('cd /home/username/repos/mysite.git && git fetch && GIT_WORK_TREE=/home/username/public_html git checkout -f main 2>&1', $out);
echo implode("\n", $out);

然后在GitHub的设置 → Webhooks下添加webhook,将Payload URL设置为https://yourdomain.com/deploy.php,并输入相同的密钥字符串。

7. 测试自动部署

在本地进行任何更改并推送:

git add .
git commit -m "test: auto deploy"
git push hosting main

打开您的网站——成功推送后更改应立即出现。

8. 主机与VPS的限制对比

功能共享主机VPS
Git 裸存储库✅ 是✅ 是
post-receive 钩子✅ 是✅ 是
运行 npm install / composer⚠️ 有限(取决于服务器)✅ 完全控制
Docker / 容器❌ 不支持✅ 是
GitHub Actions 自托管运行器❌ 不支持✅ 是
起始价格500 THB/年更高

对于标准PHP、HTML和CSS网站,共享主机上的Git钩子部署完全足够且极具性价比。对于包含构建和测试步骤的完整CI/CD管道,VPS更为适合。

提示:添加.gitignore文件以排除不必要的文件被推送:node_modules/、.env、*.log。这可以防止密钥意外出现在您的服务器上。

9. 安全的SSH密钥认证

使用SSH密钥而不是密码不仅更方便——它在安全性上也显著更高。密钥不能像密码那样被暴力破解,并且它们可以实现从本地机器到主机服务器的无缝无密码部署。

在本地生成SSH密钥

# Generate an Ed25519 key (recommended — fast and secure)
ssh-keygen -t ed25519 -C "[email protected]"

# Print the public key to copy to your hosting server
cat ~/.ssh/id_ed25519.pub

将公钥添加到您的主机服务器

# Connect with password for the first time
ssh [email protected]

# Create the authorized_keys file
mkdir -p ~/.ssh && chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys
# Paste your public key, save, then set permissions
chmod 600 ~/.ssh/authorized_keys

此后,SSH连接会自动使用密钥。运行git push hosting main将在没有任何密码提示的情况下进行部署,使工作流更快且适合脚本化自动化。

⚠️ 安全提醒:永远不要将您的私钥文件(~/.ssh/id_ed25519)提交到任何存储库。只将其保留在本地机器上,永远不要分享它。

10. 多分支部署 — 开发、预发布、生产

现实项目通常将代码分为多个环境。您可以通过修改post-receive钩子来支持这一点,在决定部署位置之前检查推送的是哪个分支。

#!/bin/bash
# post-receive hook supporting multiple branches
while read oldrev newrev refname; do
  BRANCH=$(git rev-parse --symbolic --abbrev-ref "$refname")

  if [ "$BRANCH" = "main" ]; then
    GIT_WORK_TREE=/home/username/public_html git checkout -f main
    echo "Deployed to PRODUCTION: $(date)"

  elif [ "$BRANCH" = "staging" ]; then
    GIT_WORK_TREE=/home/username/staging git checkout -f staging
    echo "Deployed to STAGING: $(date)"
  fi
done

推送到main会部署到public_html供线上访客查看。推送到staging会部署到单独的子目录,让您在发布到生产环境之前审查更改。

分支 部署目标 用途
mainpublic_html/生产环境 — 对所有访客可见
stagingstaging/预发布测试
developdev/活跃开发环境

11. 向钩子脚本添加回滚

每个可靠的部署管道都需要回滚机制。您可以直接在post-receive钩子中添加此逻辑,这样如果部署失败,服务器会自动回退到最后已知的良好提交。

#!/bin/bash
GIT_WORK_TREE=/home/username/public_html
export GIT_WORK_TREE
GIT_DIR=/home/username/repos/mysite.git
export GIT_DIR

# Record the current commit before deploying
PREV_COMMIT=$(git -C /home/username/public_html rev-parse HEAD 2>/dev/null || echo "none")

# Deploy new code
if git checkout -f main; then
  echo "Deploy successful: $(date)"
  echo "Commit: $(git rev-parse HEAD)"
else
  echo "Deploy failed — rolling back..."
  git checkout -f "$PREV_COMMIT"
  echo "Rolled back to $PREV_COMMIT"
fi

您还应该维护一个部署日志以供审计。将此行添加到您的钩子脚本:

# Append deploy record to log file
echo "$(date): branch=main commit=$(git rev-parse HEAD)" >> /home/username/deploy.log

12. 共享主机上部署方法的比较

开发者使用几种方法将代码部署到共享主机。如下比较所示,每种方法在速度、可靠性和复杂性方面有不同的权衡。

方法 易用性 错误风险 最适合
手动FTP上传低高(人为错误)完全初学者
Git钩子(裸存储库)高低大多数PHP/HTML项目
PHP Webhook接收器非常高低(如果设置了密钥)使用GitHub/GitLab的团队
GitHub Actions + SCP中等低需要CI步骤的项目

对于中小型PHP项目,带有post-receive钩子的Git裸存储库提供了最佳的简单性和可靠性平衡——特别是在已经支持SSH访问的主机方案上。设置大约需要20分钟,并提供任何技能水平的开发者都能自信维护的工作流。

提示:添加.gitignore文件以排除不必要的文件被推送:node_modules/、.env、*.log。这可以防止密钥意外出现在您的服务器上。

支持Git部署SSH访问的主机服务

AsiaGB主机从500泰铢/年起,配备SSD存储、DirectAdmin、PHP 7.4/8.2/8.3,可申请SSH访问。

查看主机方案