2.2 手动搭 LNMP:什么时候必须自己装
2.1 聊了应用镜像有多省心,这篇泼一盆冷水:有些场景,你还真得自己装。我自己的一个老项目就遇上了——一个跑了多年的站点要求 PHP 7.4(新版插件不兼容 PHP 8),还依赖一个 PHP 扩展,镜像里没有。那一刻我意识到,镜像解决的是 80% 的标准需求,剩下 20% 得靠手动。这篇就讲清楚什么情况值得动手,以及手动搭 LNMP 的完整清单。
四种必须手动装的情形
先给结论,别为了折腾而折腾。下面这四种我才建议你自己装:
| 情形 | 例子 | 为什么镜像搞不定 |
|---|---|---|
| 指定旧版或新版运行时 | PHP 7.4 老站、特定 Node 大版本 | 应用镜像只提供主流版本 |
| 需要特殊扩展或编译参数 | 某扩展、自定义 PHP 编译项 | 镜像里没装,apt 仓库也没有 |
| 多站点、多版本并存 | 一台机器跑 PHP 7.4 和 PHP 8.2 两个站 | 单镜像只带一套环境 |
| 非 WordPress 的异构应用 | 自己写的 Go/Python 服务 | 应用镜像根本没有对应方案 |
一份判断表:这次到底要不要手动
每次有人问我“我这个需求是不是得手动装”,我都让他先看下面这张判断表,逐条对号入座:
| 你的情况 | 建议方案 | 理由 |
|---|---|---|
| 只想要一个 WordPress | 应用镜像 | 镜像就是为这个场景做的 |
| 需要图形界面管服务器 | 宝塔/1Panel 镜像或后装 | 命令行对新手不友好 |
| 站点必须跑旧版 PHP | 手动 LNMP | 镜像版本你不一定能挑 |
| 缺冷门 PHP 扩展 | 手动 LNMP | 需要自己编译或配源 |
| 有合规要求,组件必须自证来源 | 手动 LNMP | 自装才能控制每一层版本和来源 |
| 一台机器要跑多个不同 PHP 版本 | 手动 LNMP | 需要多版本 php-fpm 共存 |
| 自己写的 Go/Python 服务 | 手动或纯净镜像 | 应用镜像没有现成方案 |
判断原则一句话:凡是能被现成镜像满足的,都别手动;只有需求里出现版本、扩展、合规字样的,才值得动手。
反过来,如果你只是要一个 WordPress、要可视化操作、要省事——千万别手动,回头去看 2.1。朋友的官网我用的就是镜像,手动装那台是我自己的项目,主战场分得很清楚。
再补充一种容易被误判的情形:只是单纯觉得镜像“不放心”、想自己掌控一切。这种心态我理解,但通常会演变成花两天时间调出一个厂商镜像早就调好的东西,然后每隔几个月还要自己跟一次安全补丁。控制感不等于价值,把精力留给业务内容才是小站该有的优先级。
LNMP 手动安装步骤清单
LNMP 就是 Linux + Nginx + MySQL + PHP。以 Ubuntu 系统为例,整个流程我分成五步,全程在 SSH 里完成。
第一步,更新软件源、装基础组件:
sudo apt update
sudo apt install -y nginx mysql-server php-fpm php-mysql \
php-xml php-mbstring php-curl php-gd php-imagick
一行命令把 Nginx、MySQL、PHP-FPM 和 WordPress 常用的 PHP 扩展都带上。装完先确认服务在跑:
sudo systemctl status nginx mysql php-fpm
第二步,建数据库和用户。 别用 root 跑网站,单独建一个库、一个用户,权限只给这个库:
sudo mysql <<EOF
CREATE DATABASE wpdb CHARACTER SET utf8mb4;
CREATE USER 'wpuser'@'localhost' IDENTIFIED BY '换成你自己的强密码';
GRANT ALL ON wpdb.* TO 'wpuser'@'localhost';
FLUSH PRIVILEGES;
EOF
第三步,下载并放置 WordPress 程序:
sudo mkdir -p /var/www/wordpress
cd /var/www/wordpress
sudo wget https://wordpress.org/latest.tar.gz
sudo tar -xzvf latest.tar.gz --strip-components=1
sudo chown -R www-data:www-data /var/www/wordpress
最后一条权限命令很关键,否则 WordPress 后台装插件、传图片时会找你要 FTP 凭据——这是手动装最常见的第一个坑。
第四步,配 Nginx 站点。 新建一个站点配置:
server {
listen 80;
server_name example.com;
root /var/www/wordpress;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
写好后软链到启用目录并重载:
sudo ln -s /etc/nginx/sites-available/wp /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
第五步,跑安装向导。 浏览器打开 http://服务器IP/,按页面填刚才建的库名、用户名、密码,数据库主机填 localhost,表前缀默认 wp_。填完等它建表,进后台就算成了。如果安装向导这步报数据库连接失败,回头检查第二步的库名和密码是否一致,以及 php-mysql 扩展有没有装上。
整个过程熟手二十分钟,新手照着清单走一个小时以内也能搞定。把每一步记成清单存好,因为半年后你一定忘记自己装了什么、装在哪个路径。更复杂的面板式管理可以看1Panel 面板运维手记,它比纯手工 LNMP 省心很多。
手动 LNMP 与应用镜像的对比
两种方式我都在用,差异很直观:
| 维度 | 应用镜像 | 手动 LNMP |
|---|---|---|
| 上手时间 | 十分钟 | 半小时到一小时 |
| 环境定制 | 只能用厂商给的版本 | 任意版本、任意扩展 |
| 后续维护 | 厂商调好,少操心 | 升级、备份、排错全靠自己 |
| 迁移成本 | 打快照或整体迁移 | 配置文件可复用,反而灵活 |
| 适合谁 | 第一次建站、标准需求 | 有明确定制需求的开发者 |
我的原则是:能用镜像就别手动;一旦决定手动,就把每一步记成清单存好,因为半年后你一定忘记自己装了什么。网站做大之后,服务器加云数据库的组合更稳,那是腾讯云实战手记里的路线。
还有个折中方案:先选 LNMP 应用镜像(环境装好、站点程序自己放),既省掉装 Nginx/MySQL 的基础工作,又保留对 PHP 版本和扩展的部分控制权。比纯系统镜像省事,比 WordPress 镜像灵活,适合要装自己代码又怕折腾的人。不过它毕竟是镜像的预设版本,遇到真正冷门的扩展需求,依然得回到本篇的手动路线。
踩坑与解法
坑一:装完 WordPress 让填 FTP 信息。 就是上面说的目录权限问题,chown 给 www-data 即可。
坑二:文章页 404。 Nginx 少了伪静态那行 try_files,加上再 reload。
坑三:php-fpm 的 sock 路径对不上。 Ubuntu 不同版本的路径是 /run/php/php7.4-fpm.sock 这种带版本号的,别照着旧教程抄。用这条命令看真实路径:
ls /run/php/
坑四:MySQL 装完无法登录。 Ubuntu 下 root 默认走 auth_socket,想用密码登录得先 sudo mysql 进去改认证方式,或者干脆像第二步那样新建普通用户。我自己的做法是永远新建用户、root 只留本地 socket,权限最小化比什么都踏实。
坑五:扩展装完不生效。 改了 php.ini 或装了新扩展,只重启 Nginx 是没用的,得重启 php-fpm;如果机器上有多个 PHP 版本,还要确认重启的是站点实际运行的那个。验证当前版本的命令:
php -v
php -m | grep -i imagemagick
整个安装过程我反复跑过几遍,其中一次印象很深,值得单独记下来当排错样板。
一次排错记录:扩展装不上
那次在 Ubuntu 22.04 上装 php-imagick,apt 报了一串依赖错误,大意是缺 libmagickcore 的某个开发包,而且仓库里版本对不上。第一反应是换源、apt -f install 强修,都没用。冷静下来按三步走:
- 先看错误信息里到底缺哪个具体包,而不是笼统地重试。
- 到官方软件源搜这个包名,确认需要的版本与系统版本匹配。
- 手动补上缺的依赖再重装:
sudo apt install -y libmagickcore-6.q16-6-extra
sudo apt install -y php-imagick
虽然镜像里 php-imagick 通常是预装好的,但手动环境下这类“传递依赖缺失”的问题非常典型。排错的通用套路就一句话:apt 报什么缺就补什么,报哪个版本对不上就查哪个版本,别跳过报错信息去猜。另外留个心眼:每次解决问题后把命令记进清单,半年后你绝对会感谢现在的自己。
坑六:内存不够被 OOM。 1 GB 内存的小机器跑 MySQL + PHP-FPM,默认配置偶尔会被 OOM killer 光顾。把 php-fpm 的子进程数调小(比如 max_children 改成 5),用 dmesg | tail 可以查是不是被杀过进程。
延伸阅读
- 图形化管服务器:1Panel 面板运维手记
- 建站故障排查速查:1Panel 常见问题
- 云服务器加云数据库的进阶方案:腾讯云实战手记
