本文目录导读:

我来为您详细介绍PHP代码自动部署的几种方案:
简单方案
Git Webhook + 简单脚本
// deploy.php (放在服务器上)
<?php
$secret = 'your-secret-key';
$headers = getallheaders();
$signature = $headers['X-Hub-Signature'] ?? '';
// 验证GitHub/GitLab签名
$payload = file_get_contents('php://input');
$hash = 'sha1=' . hash_hmac('sha1', $payload, $secret);
if ($hash !== $signature) {
http_response_code(403);
exit('Invalid signature');
}
// 执行部署命令
$commands = [
'cd /var/www/project && git pull origin main',
'composer install --no-dev --optimize-autoloader',
'php artisan migrate --force', // 如果有Laravel
'chown -R www-data:www-data /var/www/project',
];
foreach ($commands as $command) {
$output = shell_exec($command . ' 2>&1');
file_put_contents('/var/log/deploy.log', $output, FILE_APPEND);
}
echo 'Deploy completed';
简单Shell脚本
#!/bin/bash
# deploy.sh
set -e
PROJECT_ROOT="/var/www/project"
cd $PROJECT_ROOT
# 备份当前版本
cp -r $PROJECT_ROOT /backup/project_$(date +%Y%m%d_%H%M%S)
# 拉取最新代码
git pull origin main
# 更新依赖
if [ -f composer.json ]; then
composer install --no-dev --prefer-dist --optimize-autoloader
fi
# 执行数据库迁移
if [ -f artisan ]; then
php artisan migrate --force
fi
# 清理缓存
php artisan cache:clear
php artisan config:clear
# 设置权限
chown -R www-data:www-data $PROJECT_ROOT
chmod -R 755 storage bootstrap/cache
使用部署工具
Deployer (推荐)
// deploy.php
<?php
namespace Deployer;
require 'recipe/common.php';
// 项目配置
set('application', 'my_project');
set('repository', 'git@github.com:username/project.git');
set('git_tty', false);
set('keep_releases', 5);
// 服务器配置
host('production')
->hostname('your-server.com')
->user('deployer')
->set('deploy_path', '/var/www/project')
->set('branch', 'main');
// 上传配置
set('shared_files', ['.env']);
set('shared_dirs', ['storage', 'uploads']);
set('writable_dirs', ['storage', 'bootstrap/cache']);
// 任务定义
task('build', function () {
run('cd {{release_path}} && composer install --no-dev --prefer-dist --optimize-autoloader');
run('cd {{release_path}} && php artisan migrate --force');
run('cd {{release_path}} && php artisan optimize');
});
task('deploy', [
'deploy:info',
'deploy:prepare',
'deploy:lock',
'deploy:release',
'deploy:update_code',
'deploy:shared',
'deploy:writable',
'build',
'deploy:symlink',
'deploy:unlock',
'cleanup',
]);
after('deploy:failed', 'deploy:unlock');
Capistrano
# Capfile
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/composer'
require 'capistrano/file-permissions'
# config/deploy.rb
set :application, 'project'
set :repo_url, 'git@github.com:username/project.git'
set :deploy_to, '/var/www/project'
set :branch, `git rev-parse --abbrev-ref HEAD`.chomp
set :keep_releases, 5
# 服务器配置
server 'your-server.com', user: 'deployer', roles: %w{app web}
namespace :deploy do
after :updated, :composer_install do
on roles(:app) do
within release_path do
execute :composer, 'install --no-dev --prefer-dist --optimize-autoloader'
end
end
end
after :finished, :finalize do
on roles(:app) do
within release_path do
execute :php, 'artisan migrate --force'
execute :php, 'artisan cache:clear'
end
end
end
end
CI/CD 方案
GitHub Actions
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
- name: Install dependencies
run: composer install --no-interaction
- name: Run tests
run: php artisan test
deploy:
needs: test
runs-on: ubuntu-latest
steps:
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/project
git pull origin main
composer install --no-dev --prefer-dist
php artisan migrate --force
php artisan optimize
GitLab CI
# .gitlab-ci.yml
stages:
- test
- deploy
test:
stage: test
script:
- composer install --no-interaction
- php artisan test
deploy_production:
stage: deploy
script:
- apt-get update -y
- apt-get install -y sshpass
- sshpass -p $SERVER_PASSWORD ssh $SERVER_USER@$SERVER_HOST "
cd /var/www/project &&
git pull origin main &&
composer install --no-dev --prefer-dist -o &&
php artisan migrate --force &&
php artisan optimize
"
only:
- main
Docker 容器化部署
# Dockerfile
FROM php:8.1-fpm
# 安装扩展
RUN docker-php-ext-install pdo_mysql bcmath
# 安装Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# 设置工作目录
WORKDIR /var/www/html
# 复制源码
COPY . .
# 安装依赖
RUN composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction
# 设置权限
RUN chown -R www-data:www-data /var/www/html \
&& chmod -R 755 storage bootstrap/cache
# 启动命令
CMD ["php-fpm"]
# docker-compose.yml
version: '3.8'
services:
php:
build: .
container_name: project-php
restart: unless-stopped
working_dir: /var/www/html
volumes:
- ./:/var/www/html
environment:
- APP_ENV=production
- DB_HOST=mysql
depends_on:
- mysql
nginx:
image: nginx:alpine
container_name: project-nginx
restart: unless-stopped
ports:
- "80:80"
volumes:
- ./:/var/www/html
- ./nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
mysql:
image: mysql:8.0
container_name: project-mysql
restart: unless-stopped
environment:
- MYSQL_DATABASE=project
- MYSQL_USER=user
- MYSQL_PASSWORD=password
- MYSQL_ROOT_PASSWORD=rootpassword
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
推荐方案对比
| 方案 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|
| Webhook+脚本 | 简单、轻量 | 有限错误处理 | 小型项目 |
| Deployer | 功能强大、支持回滚 | 学习成本 | 中大型项目 |
| CI/CD | 自动化程度高、可测试 | 配置复杂 | 团队协作项目 |
| Docker | 环境一致、可扩展 | 资源消耗 | 微服务架构 |
最佳实践建议
安全措施
// 部署前安全检查
function preDeployCheck() {
// 检查仓库状态
$status = shell_exec('cd /var/www/project && git status --porcelain');
if ($status) {
throw new Exception('工作目录不干净,请先提交或回滚');
}
// 检查PHP语法
$files = shell_exec('find /var/www/project -name "*.php" -not -path "*/vendor/*"');
foreach (explode("\n", $files) as $file) {
if ($file) {
$result = shell_exec("php -l $file 2>&1");
if (strpos($result, 'No syntax errors') === false) {
throw new Exception("语法错误: $file");
}
}
}
}
回滚策略
// 回滚到上一版本
function rollback($targetRelease = null) {
$releaseDir = '/var/www/releases';
if (!$targetRelease) {
// 获取上一个版本
$releases = glob("$releaseDir/*", GLOB_ONLYDIR);
sort($releases);
$targetRelease = $releases[count($releases) - 2];
}
// 创建软链接
shell_exec("ln -sfn $targetRelease /var/www/current");
// 清理缓存
shell_exec("cd /var/www/current && php artisan optimize:clear");
// 记录日志
file_put_contents('/var/log/deploy.log',
"Rollback to $targetRelease at " . date('Y-m-d H:i:s') . "\n");
}
零停机部署
#!/bin/bash
# zero-downtime-deploy.sh
FRESH_DIR="/var/www/releases/$(date +%Y%m%d%H%M%S)"
CURRENT_DIR="/var/www/current"
# 克隆新版本
git clone -b main --depth=1 /var/www/repo $FRESH_DIR
# 安装依赖
cd $FRESH_DIR
composer install --no-dev --prefer-dist --no-interaction
# 复制环境文件
cp /var/www/shared/.env $FRESH_DIR/.env
# 创建共享目录链接
ln -s /var/www/shared/storage $FRESH_DIR/storage
ln -s /var/www/shared/uploads $FRESH_DIR/uploads
# 切换软链接
ln -sfn $FRESH_DIR $CURRENT_DIR
# 清理过期版本
find /var/www/releases -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \;
监控和日志
// 部署日志记录
class DeployLogger {
private $logFile = '/var/log/deploy.log';
public function log($message, $type = 'INFO') {
$timestamp = date('Y-m-d H:i:s');
$entry = "[$timestamp] [$type] $message\n";
file_put_contents($this->logFile, $entry, FILE_APPEND);
// 发送通知
$this->notify($message, $type);
}
private function notify($message, $type) {
// 发送到Slack
$slackUrl = getenv('SLACK_WEBHOOK_URL');
if ($slackUrl) {
// curl请求发送通知
}
// 发送邮件
if (in_array($type, ['ERROR', 'ROLLBACK'])) {
// 邮件通知管理员
}
}
}
总结建议
- 小型项目:使用 Git Webhook + 简单脚本
- 中型项目:使用 Deployer + 手动触发备份
- 大型项目:使用 GitLab CI/CD + Docker 容器化
- 关键应用:实现零停机部署 + 自动化回滚机制
选择方案时需要考虑:
- 团队技术栈
- 服务器环境
- 部署频率
- 失败容忍度
- 是否需要自动化测试
无论选择哪种方案,都要确保有完善的备份和回滚机制。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播