整站程序如何部署到服务器:从环境配置到上线运行

整站程序如何部署到服务器:从环境配置到上线运行
“把网站部署到服务器”并不只是上传文件。一个可运行的整站通常还依赖运行时、数据库、文件权限、域名解析、HTTPS 和持续运行的服务。任何一环配置不一致,都可能出现本地正常、线上报错,或者页面能打开但登录、上传、支付等功能不可用。
本文以 Ubuntu 22.04/24.04、Nginx、PHP-FPM、MySQL 为例,介绍传统 PHP 网站的完整部署流程。命令适合有 sudo 权限的 Linux 服务器;执行前应按实际系统、项目文档和云厂商规则调整。Laravel、WordPress、自研 PHP 站点都可能使用这套基础架构,但目录结构、扩展和部署命令并不相同。Node.js、Python、Java 等项目需要对应运行时,不能直接照搬 PHP-FPM 配置。
一、先确认项目类型和部署边界
开始操作前,先弄清楚项目“如何运行”,而不是只看它用了什么语言。需要向项目维护者确认以下信息:
- 入口目录是什么:是项目根目录,还是
public、web、dist等子目录。 - 运行时及版本要求:例如 PHP 8.2、Node.js 20、Python 3.12。
- 依赖安装和构建命令:是否需要 Composer、npm、数据库迁移或前端构建。
- 持久化数据在哪里:数据库、用户上传文件、缓存、日志是否位于项目目录之外。
- 是否有队列、定时任务、WebSocket、邮件发送等后台功能。
- 配置项有哪些:数据库地址、密钥、第三方服务凭证等是否从环境变量读取。
本文示例假定 PHP 网站的代码放在 /var/www/example-site,公开入口目录为 public,数据库为本机 MySQL。实际项目若要求 Nginx 指向其他目录,应以项目说明为准。尤其不要为了“能打开首页”就把网站根目录设成整个仓库根目录:配置文件、依赖清单、版本控制目录和备份文件可能因此被外部访问。
如果项目带有 Docker Compose、官方安装器或云平台部署说明,应优先评估这些方案。手工部署更适合希望直接管理系统服务、配置简单且熟悉 Linux 的场景;Docker 有利于复现运行环境,但不会自动解决数据持久化、备份、网络暴露和升级问题。
二、准备服务器和域名
选择服务器时,应结合访问量、程序资源需求、数据库大小和预算评估 CPU、内存、磁盘与带宽。开发测试站可以从较小规格开始,生产环境还要预留日志、备份和增长空间。服务器位于公网时,应确认云平台安全组与系统防火墙的规则一致。
建议使用支持密钥登录的普通管理员账户进行日常维护,通过 sudo 执行管理操作。不要把网站进程长期以 root 身份运行。SSH 端口、登录方式和账户策略应按团队的运维规范配置;修改 SSH 配置后,先验证新会话能登录,再关闭旧会话,避免把自己锁在服务器之外。
域名需要在 DNS 服务商处添加解析记录。常见做法是为主域名添加 A 记录指向服务器 IPv4 地址;若使用 IPv6,则配置 AAAA 记录。DNS 生效时间受解析缓存影响,不能仅凭本机立刻解析成功或失败判断配置是否正确。云服务器如果有独立公网地址,还应确认该地址没有变更。
三、更新系统并安装基础组件
登录服务器后先更新软件包索引与已安装组件:
sudo apt update
sudo apt upgrade -y
安装 Nginx、MySQL 和 PHP-FPM。下面列出的是一组常见扩展,具体名称会随 Ubuntu 版本和 PHP 版本变化;部署前应根据项目依赖补齐扩展,例如 intl、gd、redis。不要把“命令安装成功”当作“版本一定满足项目要求”,应核对运行时版本。
sudo apt install -y nginx mysql-server php-fpm php-mysql php-curl \
php-mbstring php-xml php-zip php-gd unzip
检查组件状态和版本:
nginx -v
php -v
sudo systemctl status nginx --no-pager
sudo systemctl status mysql --no-pager
Ubuntu 的 PHP-FPM 服务名称通常带有版本号,例如 php8.1-fpm 或 php8.3-fpm。可以用以下命令查看实际安装结果:
systemctl list-units --type=service | grep -E 'php.*fpm'
ls /run/php/
如果服务器启用了 UFW,可按需允许 SSH 和 Web 流量。务必先确认 SSH 规则,避免启用防火墙后失去远程管理能力:
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw status
sudo ufw enable
Nginx Full 通常代表允许 HTTP 的 80 端口和 HTTPS 的 443 端口。它不包含数据库端口。一般网站不应把 MySQL 的 3306 端口开放给整个公网;需要远程管理数据库时,应采用受限来源地址、VPN 或 SSH 隧道等方案,而不是无差别放行。
四、上传代码并安装依赖
生产环境优先从受控的代码仓库发布,或通过安全的文件传输方式上传构建产物。不要将数据库导出文件、私钥、生产配置和无关备份一并放进公开站点目录。以下示例假定代码已经位于服务器的目标目录:
sudo mkdir -p /var/www/example-site
sudo chown -R "$USER":"$USER" /var/www/example-site
cd /var/www/example-site
使用 Git 部署时,应使用具备必要只读权限的部署凭证,避免把个人访问令牌写进仓库地址、脚本或 shell 历史记录。示例中的仓库地址需要替换为自己的地址:
git clone https://example.com/team/site.git /var/www/example-site
如果是已有目录,可先按项目约定更新代码,再执行依赖安装。以 Composer 项目为例,生产安装常用如下命令:
cd /var/www/example-site
composer install --no-dev --prefer-dist --optimize-autoloader
该命令要求服务器已安装 Composer,并且项目依赖可以在当前 PHP 版本和系统环境下安装。不要在不了解项目依赖约束的情况下随意运行 composer update:它可能重新解析依赖版本并改变锁文件。若项目有前端资源构建,通常更稳妥的方式是在构建环境生成产物,再按项目部署要求发布;也可以在服务器构建,但需管理 Node.js 版本、磁盘空间和构建工具链。
五、创建数据库和专用账户
数据库账户应遵循最小权限原则。网站运行账户通常只需要访问自己的数据库,不需要 MySQL 管理员权限。进入 MySQL:
sudo mysql
在 MySQL 提示符中执行以下 SQL。请把示例密码替换为随机生成的强密码,不要直接照抄:
CREATE DATABASE site_db
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
CREATE USER 'site_user'@'localhost'
IDENTIFIED BY 'replace-with-a-long-random-password';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, DROP
ON site_db.* TO 'site_user'@'localhost';
FLUSH PRIVILEGES;
上述授权覆盖了许多应用的日常读写和迁移操作,但不能保证适用于所有程序。某些应用需要额外权限;另一些项目则应将结构变更和运行账户分离,让迁移账户拥有更高权限、网站运行账户只拥有必要的数据操作权限。权限应根据应用行为核对,而不是盲目授予 ALL PRIVILEGES。若数据库不在本机,账户主机范围、网络访问规则和 TLS 配置也要一并调整。
六、配置应用并保护敏感信息
很多项目使用 .env 或独立配置文件保存数据库连接、应用密钥和第三方服务凭证。生产配置应通过安全渠道写入服务器,并确保不被版本控制跟踪。以下只是格式示例,字段名称需要匹配项目实际读取的配置:
APP_ENV=production
APP_DEBUG=false
APP_URL=https://www.example.com
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=site_db
DB_USERNAME=site_user
DB_PASSWORD=replace-with-a-long-random-password
如果项目使用 Laravel,通常还需要按其文档生成应用密钥,并执行生产环境迁移、缓存配置等步骤;其他 PHP 程序的操作可能完全不同。不要因示例变量名称相似就认定框架会自动读取它们。上线前应检查项目的生产部署文档,确认密钥生成、迁移回滚和缓存清理方式。
配置文件应限制读取权限。一个常见做法是让部署用户拥有文件、让 Web 服务组能读取必要配置;具体用户和组需按系统及发布流程核实:
sudo chown root:www-data /var/www/example-site/.env
sudo chmod 640 /var/www/example-site/.env
这只是权限示例,不等同于完整的密钥管理方案。备份、日志、崩溃报告和命令行历史也可能泄露凭证。若密钥已经提交到公开仓库,应视为已经泄露并及时轮换,而不是只删除 Git 中的文件。
七、配置 Nginx 站点
创建独立的站点配置文件。下面示例适用于 PHP-FPM,假定程序入口位于 /var/www/example-site/public,域名为 www.example.com。其中 PHP-FPM socket 路径必须根据服务器实际安装版本修改;不能直接假设它一定是 php8.3-fpm.sock。
sudo nano /etc/nginx/sites-available/example-site
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example-site/public;
index index.php index.html;
client_max_body_size 20m;
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;
}
}
client_max_body_size 20m 是 Nginx 单次请求体大小限制示例,不是所有上传场景的推荐值。它必须与 PHP 的 upload_max_filesize、post_max_size 以及应用本身的限制协调。较大的上传限制会增加资源消耗和滥用风险,不应为了消除报错而无限调大。PHP 中 post_max_size 通常应不小于 upload_max_filesize;修改后需要检查 PHP-FPM 实际加载的配置并重启服务。
正则位置块会处理以 .php 结尾的请求。真实项目可能要求更严格的入口文件限制;若站点有不可信上传内容,尤其不能让用户上传目录中的 PHP 文件被当作脚本执行。应根据框架推荐配置限制可执行文件范围,并将上传文件存放在不可执行目录或独立对象存储中。
启用站点、检查配置并平滑重载 Nginx:
sudo ln -s /etc/nginx/sites-available/example-site \
/etc/nginx/sites-enabled/example-site
sudo nginx -t
sudo systemctl reload nginx
若配置报错,先依据提示修复,不要在 nginx -t 未通过时盲目重载。Ubuntu 默认站点可能与新站点争用域名或处理未知主机请求;确认默认站点是否需要后再禁用。还要确认 Nginx 用户能够遍历站点目录并读取公开文件。权限应按最小需要设置,不要用 chmod -R 777 解决访问问题。
八、设置文件权限和可写目录
Web 进程通常只需要读取程序代码,只有缓存、日志、会话或上传目录需要写入。以 www-data 为 Web 服务用户的系统,可按项目实际目录设置组权限,例如:
sudo chown -R "$USER":www-data /var/www/example-site
sudo find /var/www/example-site -type d -exec chmod 750 {} \;
sudo find /var/www/example-site -type f -exec chmod 640 {} \;
上述设置不一定适用于所有发布流程:部署用户、PHP-FPM 用户、共享组和发布工具可能不同。项目要求 Web 进程写入某些目录时,只对这些目录单独授权,例如:
sudo chown -R www-data:www-data /var/www/example-site/storage
sudo chmod -R u+rwX,g+rwX /var/www/example-site/storage
路径仅为示例,先确认目录确实存在且需要写入。避免把整个代码目录交给 Web 进程写入,否则一旦应用存在漏洞,攻击者可能更容易篡改程序文件。权限调整后,检查目录各级访问权限和服务日志,比直接放宽所有权限更可靠。
九、迁移数据、初始化和后台任务
如果是新站,按项目文档执行数据库迁移和初始数据导入;如果是旧站迁移,应先备份源数据库与上传文件,再确认字符集、数据库版本、时区和数据一致性。大体流程通常是:停写或进入维护模式、导出数据、传输备份、导入目标库、部署兼容代码、运行迁移、验证功能,再恢复服务。不同框架的迁移是否可回滚、是否锁表、是否兼容旧代码,需要事先验证。
涉及长任务、消息队列、定时清理或定期发送邮件的系统,通常不能只部署 Web 服务。必须确认 worker 是否需要由 systemd、Supervisor 或容器编排系统守护,任务是否能在重复执行时保持正确,以及定时任务是否会在多台机器上重复运行。不要在网页请求中执行持续运行的后台进程。
如果应用用 Linux 定时任务执行命令,应以合适的服务用户配置,并确认工作目录、环境变量和日志输出。交互式终端能运行,不代表 cron 环境也能运行,因为两者的 PATH 和环境变量可能不同。定时任务应有失败告警或日志检查机制。
十、配置 HTTPS 并验证上线
在域名解析正确且 80 端口可从公网访问后,可以使用 Certbot 获取并配置 Let’s Encrypt 证书。Ubuntu 上的安装方式会随版本和官方建议变化,按 Certbot 当前文档选择 apt 或 Snap 安装方式。若已通过 apt 安装 Nginx 插件,可使用类似命令申请证书:
sudo certbot --nginx -d example.com -d www.example.com
该命令要求域名已指向当前服务器、验证流量能到达服务器,且 Nginx 配置可用。证书签发失败时,先核对 DNS、云安全组、防火墙、域名拼写和代理/CDN 设置。不要把证书文件权限放宽到所有用户可读。证书续期机制也要验证,例如按 Certbot 文档执行续期测试,并确认续期成功后 Nginx 能加载新证书。
上线后至少检查以下项目:
- HTTP 和 HTTPS 是否按预期访问,主域名与带
www域名是否统一跳转。 - 首页、登录、表单提交、上传、搜索和关键业务流程是否正常。
- 数据库连接、邮件发送、后台任务、定时任务和第三方接口是否正常。
- 公开目录之外的配置文件、仓库文件和备份文件是否无法通过 URL 访问。
- 日志是否持续出现 PHP 错误、Nginx 502、数据库拒绝连接或权限错误。
查看 Nginx 和 PHP-FPM 服务状态、日志的常用命令如下。PHP 服务名称需替换成实际版本:
sudo systemctl status nginx --no-pager
sudo journalctl -u nginx -n 100 --no-pager
sudo journalctl -u php8.3-fpm -n 100 --no-pager
sudo tail -n 100 /var/log/nginx/error.log
sudo tail -n 100 /var/log/nginx/access.log
排查时先区分请求是否到达服务器:DNS 解析失败与应用报错不是一类问题;Nginx 返回 502 常见于 PHP-FPM 未运行、socket 路径错误或权限不匹配;页面返回 500 通常要结合 PHP 和应用日志定位;上传失败则要同时检查 Nginx、PHP 和应用层限制。不要公开展示详细错误堆栈或开启生产环境调试模式。
十一、备份、更新与回滚
上线并不意味着部署结束。至少要为数据库、用户上传文件、关键配置和证书相关材料制定备份策略。备份应存放在与原服务器不同的故障域,限制访问权限,并定期进行恢复演练。只有“备份任务显示成功”并不足以证明备份可用。
以下是本机 MySQL 数据库导出的基本示例。生产环境应避免在命令行参数中明文暴露密码;可以使用受保护的客户端配置或合适的秘密管理方式。导出文件包含敏感数据,应限制权限并尽快传输到安全的备份位置。
umask 077
mysqldump --single-transaction site_db > /secure-backup/site_db.sql
日常发布宜采用可回滚的流程:保留当前版本,部署新版本到新目录或版本化发布目录,更新依赖与配置,执行经过验证的迁移,再切换当前版本指向。数据库变更若不向后兼容,代码回滚也未必能恢复服务,因此数据库迁移要单独设计。不要在没有备份和回滚方案的情况下直接覆盖生产目录。
十二、常见错误速查
- 网站返回默认欢迎页:检查域名是否命中正确的 Nginx
server_name,站点软链接是否启用,以及默认站点是否抢先匹配。 - 首页能开,刷新子页面却 404:确认应用路由需要的
try_files回退规则与框架文档一致。 - PHP 请求下载源码或显示 502:检查 PHP-FPM 是否运行、socket 路径是否正确,以及 Nginx 中 PHP 处理配置是否加载。
- 报数据库连接错误:核对数据库服务状态、库名、用户名、密码、主机地址和账户允许的来源范围;不要先把数据库端口开放到公网。
- 提示权限不足:检查 PHP-FPM 的运行用户、目录逐级权限和目标目录是否需要写入;不要用全目录 777 掩盖问题。
- 上传总是失败:同时检查 Nginx 的请求体限制、PHP 的上传和 POST 限制、磁盘空间及应用校验规则。
- 线上出现调试信息:关闭生产调试选项,保护日志和配置文件,并排查是否通过公开目录暴露了仓库或备份。
- 重启后功能异常:检查是否依赖临时目录、未持久化文件、交互式 shell 环境变量或没有设置开机启动的后台服务。
结语
整站部署的核心不是记住一串命令,而是弄清代码、运行时、数据库、文件权限、域名和后台服务之间的关系。本文提供的 Nginx 与 PHP-FPM 配置适用于一类常见 PHP 站点,不是所有项目的通用模板。上线前以项目文档为准,逐项验证依赖和关键业务;上线后持续检查日志、备份恢复、证书续期和安全更新,才能让网站稳定运行。



