在 DigitalOcean Droplet 上部署 PHP Laravel 应用指南 2026
在自己的 DigitalOcean Droplet 上将 Laravel 部署到生产环境可以让您完全灵活地控制环境,与 App Platform 等自动管理基础设施的 PaaS 产品不同。本指南将分步骤指导您完成从服务器准备、PHP 和 Composer 安装、Nginx、PHP-FPM、队列工作进程和 SSL 配置的所有环节,使其为实际生产使用做好准备。我们还将介绍管理自己服务器的团队常见的错误和最佳实践。
目录
准备 Droplet 并安装 PHP/Composer
部署 Laravel 首先需要选择适合应用实际负载的 Droplet 大小。对于刚起步或用户很少的项目,Basic 套餐 1 GiB RAM / 1 vCPU / 25GB SSD,价格为 $6/月,但对于有持续流量和队列工作进程的真正生产网站,我们建议从 2 GiB RAM / 1 vCPU / 50GB SSD 的 $12/月起(2,000 GiB 流量),因为 PHP-FPM 和 MySQL 在流量增加时很容易一起消耗大量内存。对于更重的处理任务,考虑 4 GiB RAM / 2 vCPU 的 $24/月套餐。泰国用户应选择 sgp1(新加坡)区域,它在 DigitalOcean 15 个区域中延迟最低,其次是 blr1(班加罗尔)。对于操作系统,我们建议 Ubuntu 24.04 LTS,因为它通过 PPA 提供更新的 PHP 版本。
创建 Droplet 后,SSH 连接并先使用 apt update && apt upgrade -y 更新系统。然后启用云防火墙(免费,无额外费用)以限制访问只允许 SSH (22)、HTTP (80) 和 HTTPS (443) 来减小攻击面。接下来,使用 ondrej 的 PPA 通过 add-apt-repository ppa:ondrej/php -y && apt update 安装 PHP 8.3 及 Laravel 扩展,然后使用 apt install php8.3 php8.3-fpm php8.3-mysql php8.3-mbstring php8.3-xml php8.3-bcmath php8.3-curl php8.3-zip php8.3-gd -y 安装。使用 php -v 验证版本。最后,使用官方安装程序 curl -sS https://getcomposer.org/installer | php 安装 Composer,然后使用 mv composer.phar /usr/local/bin/composer 将其移动到 PATH,并在继续安装 Laravel 前使用 composer --version 验证。
- 生产最低 Droplet 配置为 2 GiB RAM / 1 vCPU($12/月)或更高 — $6 套餐仅用于测试
- 泰国用户选择 sgp1(新加坡)区域以获得最低延迟,blr1(班加罗尔)作为备用
- 启用免费云防火墙以在安装任何软件前限制端口到 22/80/443
- 通过 ondrej/php PPA 安装 PHP 8.3 及扩展:mbstring、xml、bcmath、curl、zip、gd、mysql
- 通过官方安装程序安装 Composer,然后移动到 /usr/local/bin/composer
安装 Laravel 并配置 .env
根据我们的实测——服务器准备好后,有两种方法将 Laravel 代码放到 Droplet 上:使用 composer create-project laravel/laravel myapp 创建新项目或使用 git clone [email protected]:yourteam/myapp.git /var/www/myapp 克隆现有仓库,然后进入目录并使用 composer install --no-dev --optimize-autoloader 为生产环境安装依赖。--no-dev 标志会跳过 phpunit 等开发包,--optimize-autoloader 会创建类映射以在生产环境中加快加载。
接下来,使用 cp .env.example .env 配置环境文件,然后使用 php artisan key:generate 生成新的 APP_KEY。永远不要重用本地的 APP_KEY,因为它加密会话和 cookie。然后编辑 .env 以匹配生产环境,例如 APP_ENV=production、APP_DEBUG=false(关键 — 留启用调试会向用户暴露堆栈跟踪和配置)和 APP_URL=https://yourdomain.com 以匹配您的实际域名,这样 Laravel 在电子邮件和资产中生成的 URL 才是正确的。使用 php artisan storage:link 为上传创建符号链接,并设置权限以便 Web 服务器可以写入日志/缓存,使用 chown -R www-data:www-data storage bootstrap/cache 后跟 chmod -R 775 storage bootstrap/cache。这一步常被忽视,但是 500 错误的常见原因。最后,使用 php artisan about 测试以验证环境与您的意图相符,然后再在下一步连接到数据库。
- 使用 composer create-project 创建新项目或 git clone 现有仓库到 /var/www/myapp
- 仅在生产环境使用 composer install --no-dev --optimize-autoloader;不要安装开发依赖
- APP_KEY 必须每次都用 php artisan key:generate 生成新的;永远不要重用本地密钥
- 始终设置 APP_ENV=production 和 APP_DEBUG=false 以防止错误数据泄露
连接到 MySQL
Laravel 支持在同一 Droplet 上自托管 MySQL 或 DigitalOcean 的托管数据库作为单独实例;各有各的权衡。自托管使用 apt install mysql-server -y 无需额外费用,但您需要自己管理备份、补丁和调整。DigitalOcean 的托管 MySQL 起价 $15.15/月,基础套餐为 1 vCPU / 1 GiB RAM 和 10-30GiB 存储,提供开箱即用的自动备份、故障转移和指标 — 适合需要高稳定性或团队不想管理数据库的项目。两者都可以通过 VPC(私有网络,免费)连接,这样 Droplet 和数据库之间的流量不会穿过公网。
如果选择自托管,安装后运行 mysql_secure_installation 来设置 root 密码并关闭基本漏洞。然后使用 CREATE DATABASE myapp; CREATE USER 'myapp'@'localhost' IDENTIFIED BY 'strong-password'; GRANT ALL PRIVILEGES ON myapp.* TO 'myapp'@'localhost'; FLUSH PRIVILEGES; 创建数据库和应用特定用户。永远不要在生产应用中使用 root 用户。然后编辑 .env 以匹配实际配置:DB_CONNECTION=mysql、DB_HOST=127.0.0.1、DB_PORT=3306、DB_DATABASE=myapp、DB_USERNAME=myapp、DB_PASSWORD=strong-password。对于托管数据库,使用您的控制面板中的私有主机名替换 DB_HOST。最后,使用 php artisan migrate --force 真正运行迁移;--force 标志在生产环境中是必需的,因为当检测到 APP_ENV=production 时,Laravel 不会在没有显式确认的情况下运行迁移,这是一项安全措施。
- 自托管 MySQL 免费但你需要自己管理备份/补丁 — 托管 MySQL $15.15/月(1 vCPU/1 GiB RAM,10-30GiB)有自动备份
- 通过 VPC(免费)连接托管数据库以获得安全性并比公网降低延迟
- 为应用创建特定数据库用户;永远不要在 .env 中将 root 用于生产
配置 Nginx 和 PHP-FPM
Nginx 作为前端 Web 服务器,接收请求并通过套接字将 PHP 文件转发到 PHP-FPM 进行处理。首先使用 apt install nginx -y 安装,然后在 /etc/nginx/sites-available/myapp 创建新配置文件,其中根目录仅指向 Laravel 的 public 目录而不是项目根目录,因为 .env 和应用代码绝不能直接通过 URL 访问。最小配置示例是 server { listen 80; server_name yourdomain.com; root /var/www/myapp/public; index index.php; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm.sock; } location ~ /\.(?!well-known).* { deny all; } }。常见错误是 fastcgi_pass 路径与实际安装版本的 PHP-FPM 套接字不匹配 — 始终先用 ls /run/php/ 验证。
编写配置后,使用 ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/ 创建符号链接启用它,然后在重新加载前始终使用 nginx -t 测试语法。如果没有错误,使用 systemctl reload nginx 重新加载。在 PHP-FPM 端,检查 /etc/php/8.3/fpm/pool.d/www.conf 处的池配置,尤其是 pm.max_children,应与您的 Droplet 的 RAM 相匹配 — 在 2 GiB 机器上,不要设置过高否则会耗尽内存,因为每个子进程单独消耗 RAM。调整池配置后,使用 systemctl restart php8.3-fpm 重启,然后打开浏览器测试域名并验证看到 Laravel 欢迎页面或您的实际应用。
- Nginx 根目录必须仅指向 /var/www/myapp/public,永远不是项目根目录
- 用 ls /run/php/ 验证真实套接字路径,然后配置 fastcgi_pass 以匹配它
- 重新加载前始终使用 nginx -t 测试语法以防止停机
- 使用 location ~ /\.(?!well-known).* { deny all; } 阻止 .env 等点文件访问
- 在 PHP-FPM 池中调整 pm.max_children 以匹配您的 Droplet 的可用 RAM
队列工作进程和 SSL
有后台任务如发送电子邮件或处理文件的 Laravel 应用应使用队列而不是同步处理以避免让用户等待。首先测试运行 php artisan queue:work,但这个命令在 SSH 会话关闭或服务器重启时会立即停止,所以您需要 Supervisor 来保持工作进程运行并在崩溃时自动重启。使用 apt install supervisor -y 安装 Supervisor,然后在 /etc/supervisor/conf.d/myapp-worker.conf 创建配置文件,内容大致如下 [program:myapp-worker] process_name=%(program_name)s_%(process_num)02d command=php /var/www/myapp/artisan queue:work --sleep=3 --tries=3 --max-time=3600 autostart=true autorestart=true numprocs=2 user=www-data。然后运行 supervisorctl reread && supervisorctl update && supervisorctl start myapp-worker:*。关键部分是每次部署新代码时,必须运行 php artisan queue:restart 以通知旧工作进程完成其任务并重新加载新代码,否则它们会继续运行内存中缓存的旧代码。
对于 SSL,通过 Certbot 使用 Let's Encrypt,它颁发免费证书并自动续期。使用 apt install certbot python3-certbot-nginx -y 安装,然后在一个命令中颁发证书并自动配置 Nginx certbot --nginx -d yourdomain.com -d www.yourdomain.com。Certbot 设置 systemd 定时器以每 90 天自动续期一次。首先使用 certbot renew --dry-run 验证。在使用 SSL 前,确保云防火墙打开了 443 端口。设置 SSL 后,强制从 http 重定向到 https 以保护所有用户。
- 直接运行 php artisan queue:work 会在会话关闭时停止;使用 Supervisor 使其永久运行
- 部署新代码后始终运行 php artisan queue:restart,否则工作进程会继续运行内存中的旧代码
- 通过 Let's Encrypt/Certbot 免费获得 SSL:certbot --nginx -d yourdomain.com 自动颁发和安装证书
何时使用这种方法(真实用例)
自托管 Droplet 上的 Laravel 适合想要对环境有完全控制的团队 — 比如需要自定义 PHP 扩展、自己调整 MySQL 或运行多个 cron 作业和具有自定义调度的队列工作进程。它还能保持成本可预测,因为您按 Droplet 大小支付固定月费,而不是像无服务器服务那样的可变成本。另一方面,如果您的团队没有专业的系统管理员或更喜欢快速部署而不管理 Nginx/PHP-FPM/SSL,DigitalOcean App Platform 是更好的选择。它是一个 PaaS,自动从 Git 仓库构建和部署,起价 $5/月的共享容器(1 vCPU、512MiB RAM、50GiB 流量)到 $50/月(2 vCPU、4GiB RAM、250GiB 流量)用于更大的工作负载。 另一个考虑是数据库。对于小项目或预算紧张且您接受自己管理风险的情况,在同一 Droplet 上运行 MySQL 就足够了,但一旦应用有真实用户并需要高正常运行时间和自动备份,迁移到起价 $15.15/月的托管 MySQL 就值得节省时间。对于预期快速扩展并运行多个实例负载均衡器的项目,从一开始就考虑 DigitalOcean Kubernetes (DOKS) — 控制平面免费,您只需为节点池按标准 Droplet 价格(每个节点最低 $12/月)付费。总体而言,本指南中的单一 Droplet 方法最适合您的团队能够管理系统并想要完全控制堆栈的中小项目。
- 适合想要完整堆栈控制以自定义 PHP、调整 MySQL 和管理 cron/队列工作进程的团队
- 按 Droplet 大小的固定月费使预算相比无服务器可预测
- 没有系统管理员或更喜欢快速部署的团队应考虑 App Platform($5-$50/月用于小中型容器)
常见错误和修复
最常见的错误是部署后出现 500 错误,通常由于 storage 或 bootstrap/cache 权限问题。修复方法是再次运行 chown -R www-data:www-data storage bootstrap/cache && chmod -R 775 storage bootstrap/cache,并检查 storage/logs/laravel.log 处的实际日志而不是猜测。另一个问题是编辑了 .env 但应用仍使用旧值,因为 Laravel 缓存了配置。修复方法是先运行 php artisan config:clear,然后 php artisan config:cache 来缓存新值。
一个常见的陷阱是 Nginx fastcgi_pass 路径与实际 PHP-FPM 套接字不匹配,特别是在升级 PHP 版本如 8.2 到 8.3 并忘记更新配置后,导致 Nginx 返回 502 Bad Gateway。始终使用 ls /run/php/ 检查您的配置。对于队列工作进程,部署后忘记运行 php artisan queue:restart 意味着工作进程继续运行旧代码。从数据库方面,SQLSTATE[HY000] [2002] Connection refused 通常意味着 MySQL 的 bind-address 被锁定在 127.0.0.1 但您的 .env 中的 DB_HOST 指向其他地方,或用户没有从连接主机被授予权限。最后,在 512MiB-1GiB RAM 的小 Droplet 上,composer install 可能因内存不足而崩溃。修复方法是在运行 composer 前通过 fallocate -l 1G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile 临时添加交换。
- 部署后 500 错误 → 先检查 storage/logs/laravel.log 和 storage/bootstrap/cache 权限
- 更改 .env 无效 → 每次都必须运行 php artisan config:clear 然后 config:cache
- 502 Bad Gateway → Nginx 中的 fastcgi_pass 路径与实际 PHP-FPM 套接字不匹配,特别是在 PHP 版本升级后
最佳实践(最佳实践)
为避免每次部署时面向用户的停机,使用零停机部署:将新代码拉到单独的发布文件夹,然后仅在一切就绪后切换当前符号链接指向新发布(Deployer 和 Envoyer 等工具使用的方法),而不是在运行代码上面 git pull,这可能会在部署中途向用户显示部分更新。每次重启前,使用 php artisan config:cache && php artisan route:cache && php artisan view:cache 缓存配置、路由和视图以减少每个请求的处理。永远不要向 git 提交 .env — 从一开始就设置 .gitignore。
对于计划任务,仅创建一个调用 Laravel 调度器的 cron 行 * * * * * cd /var/www/myapp && php artisan schedule:run >> /dev/null 2>&1,然后在代码中定义所有任务,让 Laravel 管理它们。让 Supervisor 处理队列工作进程如所述,这样它们在崩溃或重启时自动重启。对于备份,定期拍摄 Droplet 快照 — 它们仅需 $0.06/GiB/月,对于灾难恢复是无价的。启用 DigitalOcean 监控(每个账户免费 1 个正常运行时间检查)以在服务器有问题时提醒您。对于安全性,禁用 SSH 密码登录仅使用 SSH 密钥,使用云防火墙(免费)限制端口,如果您计划未来迁移或重建,从一开始绑定保留 IP — 当连接到活跃 Droplet 时它是免费的,为您从每次服务器更改更新 DNS 节省时间。
- 使用发布文件夹 + 符号链接切换进行零停机部署,而不是在实时代码上 git pull
- 每次部署前缓存 config/route/view(config:cache、route:cache、view:cache),永远不要向 git 提交 .env
- 使用 Laravel 调度器通过单个 cron 行(php artisan schedule:run 每分钟)而不是多个 cron 条目
- 定期拍摄 Droplet 快照($0.06/GiB/月)并启用免费监控和正常运行时间检查