从零搭建LNMP环境:Nginx+PHP+MySQL部署与优化实战

📅 2026/8/18 3:59:19
从零搭建LNMP环境:Nginx+PHP+MySQL部署与优化实战
1. 项目概述为什么是LNMP如果你刚接触服务器运维或者想自己搭个网站、博客大概率会听到LAMP、LNMP这些词。LAMP是LinuxApacheMySQLPHP而LNMP就是把中间的AApache换成了NNginx。我为什么更推荐新手从LNMP开始原因很简单Nginx在处理高并发静态请求时性能比Apache好得多内存占用也更低配置语法对新手来说更直观。现在绝大多数网站尤其是个人博客、中小型企业站后端逻辑用PHP前端用Nginx做Web服务和反向代理数据存MySQL这套组合拳是经过市场验证的、最稳定高效的方案之一。网上教程很多但很多要么太老软件版本对不上要么太简略关键配置一笔带过新手照着做十有八九会卡在某个报错上。这篇内容我会基于最新的稳定版软件在纯净的CentOS 7/8或Ubuntu 20.04/22.04系统上带你从零开始一步步把LNMP环境搭起来。不止是安装我会重点讲清楚每个配置项是干什么的为什么这么配以及我踩过的那些坑。目标就一个让你不仅能成功搭起来还能理解背后的原理以后出问题了知道去哪儿排查。2. 环境准备与核心思路在动手敲命令之前理清思路比盲目操作更重要。LNMP的部署核心思路是“分而治之逐个击破最后联调”。我们不是在安装一个叫“LNMP”的软件包而是在Linux系统上分别安装并配置Nginx、MySQL、PHP这三个独立的服务然后让它们协同工作。2.1 系统选择与初始化首先得有个Linux服务器。可以是云服务器ECS也可以是本地虚拟机VMware/VirtualBox。对于新手我强烈建议用CentOS 7或Ubuntu 20.04 LTS。这两个系统资料最全社区支持最好遇到问题容易搜到答案。本文的命令会兼顾两者并明确指出差异。拿到一个全新的系统第一件事不是安装软件而是做系统更新和基础配置这能避免很多后续的权限和依赖问题。更新系统软件包列表这相当于刷新一下软件仓库的目录确保接下来安装的是最新版本。# CentOS 7 sudo yum update -y # Ubuntu 20.04 sudo apt update -y安装常用的编译工具和依赖后续编译安装某些扩展可能会用到。# CentOS 7 sudo yum groupinstall Development Tools -y sudo yum install epel-release -y sudo yum install wget vim net-tools -y # Ubuntu 20.04 sudo apt install build-essential -y sudo apt install wget vim net-tools -y配置防火墙如果开启云服务器通常有安全组本地虚拟机或某些环境下可能需要配置系统防火墙提前为Nginx80/443端口和后续可能用到的MySQL3306端口生产环境切勿对外放行。# CentOS 7 (使用firewalld) sudo firewall-cmd --permanent --add-servicehttp sudo firewall-cmd --permanent --add-servicehttps # 通常MySQL端口不对外这里仅演示实际请按需 # sudo firewall-cmd --permanent --add-port3306/tcp sudo firewall-cmd --reload # Ubuntu 20.04 (使用ufw) sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw reload注意很多新手卡在第一步用root用户直接操作。虽然方便但存在风险。建议创建一个具有sudo权限的普通用户来操作。adduser yourusername然后usermod -aG sudo yourusername(Ubuntu) 或usermod -aG wheel yourusername(CentOS)。2.2 软件安装方案选型源码编译 vs 包管理器这是第二个关键决策点。安装软件主要有两种方式通过系统自带的包管理器yum/apt安装或者下载源码自己编译安装。包管理器安装推荐给新手优点是简单、快速、自动处理依赖关系。缺点是软件版本可能不是最新的且配置文件的位置、编译参数都是发行版维护者定的定制性稍差。源码编译安装优点是可以自定义版本、编译参数优化性能、开启特定功能对软件的控制力最强。缺点是过程复杂、耗时需要手动解决依赖容易出错。对于LNMP环境搭建我个人的建议是Nginx和PHP可以考虑源码编译以获得更好性能和灵活性而MySQL强烈建议使用包管理器或官方仓库安装。因为MySQL的编译极其耗时且依赖复杂用官方包能确保稳定和安全更新。本文为了兼顾新手和深度会采用一种混合方案Nginx和PHP从源码编译MySQL用官方仓库安装。如果你追求极致简便三者全部用包管理器安装也可以我会在相应部分给出命令。3. 核心组件安装与配置详解接下来我们进入核心环节逐个安装和配置三大组件。顺序可以是任意的但通常我习惯先装MySQL再装PHP最后装Nginx因为Nginx的配置需要指向已安装的PHP。3.1 MySQL 8.0 安装与安全加固MySQL是数据库存放你网站的所有数据文章、用户信息等。我们选择安装目前广泛使用的MySQL 8.0版本。添加MySQL官方仓库并安装以CentOS 7为例# 下载并安装MySQL官方的Yum仓库 wget https://dev.mysql.com/get/mysql80-community-release-el7-6.noarch.rpm sudo rpm -ivh mysql80-community-release-el7-6.noarch.rpm # 安装MySQL服务器 sudo yum install mysql-community-server -yUbuntu系统可以使用APT仓库命令类似具体参考MySQL官网。启动MySQL并设置开机自启sudo systemctl start mysqld sudo systemctl enable mysqld获取初始临时密码并进行安全设置 MySQL 8.0安装后会为root用户生成一个临时密码保存在日志文件中。sudo grep temporary password /var/log/mysqld.log复制这个密码然后运行安全配置脚本sudo mysql_secure_installation接下来会有一系列交互式提问输入刚才查到的临时密码。是否修改root密码必须选是并设置一个强密码包含大小写字母、数字、特殊字符。是否移除匿名用户选是。是否禁止root远程登录生产环境建议选是然后创建一个用于远程管理的专用账户权限最小化原则。是否删除测试数据库选是。是否立即重新加载权限表选是。创建用于网站的数据库和用户可选但建议 不要直接用root用户连接网站程序。我们创建一个专用的数据库和用户。mysql -u root -p # 输入你刚设置的root密码在MySQL提示符下执行-- 创建一个名为mywebsite的数据库 CREATE DATABASE mywebsite CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 创建一个用户webuser并设置密码 CREATE USER webuserlocalhost IDENTIFIED BY YourStrongPassword123!; -- 授予webuser用户对mywebsite数据库的所有权限 GRANT ALL PRIVILEGES ON mywebsite.* TO webuserlocalhost; -- 刷新权限使更改生效 FLUSH PRIVILEGES; -- 退出 EXIT;实操心得字符集一定要用utf8mb4而不是老的utf8。utf8在MySQL中最多只支持3字节存不了常见的emoji表情而utf8mb4是完整的4字节UTF-8编码。这是新手容易忽略但后期改起来很麻烦的点。3.2 PHP 8.x 源码编译安装与优化PHP是处理动态网页的“引擎”。我们选择编译安装PHP 8.2或8.3并集成Nginx和MySQL所需的扩展。安装编译依赖PHP编译需要一堆库先装好。# CentOS 7 sudo yum install gcc gcc-c make libxml2-devel openssl-devel curl-devel libjpeg-devel libpng-devel freetype-devel libzip-devel -y # Ubuntu 20.04 sudo apt install gcc make autoconf libxml2-dev libssl-dev pkg-config libcurl4-openssl-dev libjpeg-dev libpng-dev libfreetype6-dev libzip-dev -y下载PHP源码并解压cd /usr/local/src # 从官网镜像下载版本号可替换为最新稳定版如8.3.8 sudo wget https://www.php.net/distributions/php-8.2.20.tar.gz sudo tar -zxvf php-8.2.20.tar.gz cd php-8.2.20配置编译参数这是最关键的一步决定了PHP包含哪些功能。sudo ./configure \ --prefix/usr/local/php8.2 \ --with-config-file-path/usr/local/php8.2/etc \ --enable-fpm \ --with-fpm-usernginx \ --with-fpm-groupnginx \ --with-mysqlimysqlnd \ --with-pdo-mysqlmysqlnd \ --with-openssl \ --with-curl \ --with-zlib \ --with-zip \ --with-jpeg \ --with-freetype \ --enable-mbstring \ --enable-gd \ --enable-opcache--prefix指定安装目录。--enable-fpm编译PHP-FPMFastCGI Process Manager这是Nginx与PHP通信的桥梁必须开启。--with-fpm-user/group指定PHP-FPM进程运行的用户和组这里设为nginx需要先创建该用户或后面再改。--with-mysqli和--with-pdo-mysql启用MySQL数据库支持使用原生的mysqlnd驱动性能更好。其他--with-*参数是启用各种常用扩展GD库处理图片、cURL处理网络请求等。--enable-opcache强烈建议开启这是PHP的字节码缓存能极大提升执行效率。编译与安装这个过程比较长取决于服务器性能。sudo make -j $(nproc) # $(nproc)会自动使用所有CPU核心加速编译 sudo make install配置PHP和PHP-FPM复制配置文件sudo cp /usr/local/src/php-8.2.20/php.ini-production /usr/local/php8.2/etc/php.ini sudo cp /usr/local/php8.2/etc/php-fpm.conf.default /usr/local/php8.2/etc/php-fpm.conf sudo cp /usr/local/php8.2/etc/php-fpm.d/www.conf.default /usr/local/php8.2/etc/php-fpm.d/www.conf编辑PHP-FPM配置文件/usr/local/php8.2/etc/php-fpm.d/www.conf确保用户组设置正确sudo vim /usr/local/php8.2/etc/php-fpm.d/www.conf找到user和group行修改为如果系统没有nginx用户可以先改成www-data或apache但要和后面Nginx运行用户一致user nginx group nginx创建PHP-FPM服务文件以Systemd为例sudo vim /etc/systemd/system/php8.2-fpm.service写入以下内容[Unit] DescriptionPHP 8.2 FastCGI Process Manager Afternetwork.target [Service] Typeforking PIDFile/run/php8.2-fpm.pid ExecStart/usr/local/php8.2/sbin/php-fpm --daemonize --fpm-config /usr/local/php8.2/etc/php-fpm.conf ExecReload/bin/kill -USR2 $MAINPID ExecStop/bin/kill -QUIT $MAINPID [Install] WantedBymulti-user.target启动PHP-FPM并设置开机自启sudo systemctl daemon-reload sudo systemctl start php8.2-fpm sudo systemctl enable php8.2-fpm踩坑记录编译过程中最常见的错误是“找不到xxx.h头文件”。这几乎都是因为缺少对应的-devel或-dev开发包。根据报错信息用yum search或apt search查找并安装对应的开发包即可。例如报错zip.h not found就安装libzip-devel(CentOS)或libzip-dev(Ubuntu)。3.3 Nginx 1.x 源码编译安装与核心配置Nginx是我们的Web服务器和反向代理。同样采用源码编译以便开启我们需要的模块。安装Nginx编译依赖# CentOS 7 sudo yum install pcre-devel zlib-devel openssl-devel -y # Ubuntu 20.04 sudo apt install libpcre3-dev zlib1g-dev libssl-dev -y下载Nginx源码并解压cd /usr/local/src # 下载稳定版例如1.24.0 sudo wget http://nginx.org/download/nginx-1.24.0.tar.gz sudo tar -zxvf nginx-1.24.0.tar.gz cd nginx-1.24.0配置编译参数sudo ./configure \ --prefix/usr/local/nginx \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_realip_module \ --with-http_gzip_static_module \ --with-http_stub_status_module \ --with-stream--with-http_ssl_module支持HTTPS必备。--with-http_v2_module支持HTTP/2提升性能。--with-http_stub_status_module启用状态页方便监控。--with-stream支持TCP/UDP代理用途更广。编译与安装sudo make -j $(nproc) sudo make install创建Nginx用户和组sudo groupadd nginx sudo useradd -g nginx -s /sbin/nologin nginx配置Nginx服务文件sudo vim /etc/systemd/system/nginx.service写入以下内容[Unit] Descriptionnginx - high performance web server Documentationhttp://nginx.org/en/docs/ Afternetwork.target [Service] Typeforking PIDFile/usr/local/nginx/logs/nginx.pid ExecStart/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf ExecReload/bin/kill -s HUP $MAINPID ExecStop/bin/kill -s TERM $MAINPID PrivateTmptrue [Install] WantedBymulti-user.target修改Nginx主配置文件 编辑/usr/local/nginx/conf/nginx.conf进行关键修改。在文件顶部确保第一行是user nginx nginx;指定运行用户。找到server块这是默认的站点配置。我们将其修改为一个能处理PHP请求的配置模板server { listen 80; server_name localhost; # 这里替换成你的域名或IP # 设置网站根目录这里假设为 /var/www/html root /var/www/html; index index.php index.html index.htm; location / { try_files $uri $uri/ 404; } # 关键配置将所有.php文件的请求转发给PHP-FPM处理 location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; # PHP-FPM监听的地址和端口 fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } # 禁止访问.htaccess等隐藏文件 location ~ /\.ht { deny all; } }创建网站目录并设置权限sudo mkdir -p /var/www/html sudo chown -R nginx:nginx /var/www/html启动Nginx并设置开机自启sudo systemctl daemon-reload sudo systemctl start nginx sudo systemctl enable nginx4. 环境联调与功能验证三大组件都安装配置好了现在需要验证它们是否能协同工作。4.1 测试Nginx与PHP-FPM通信在网站根目录创建一个PHP信息文件sudo vim /var/www/html/info.php写入内容?php phpinfo(); ?在浏览器中访问你的服务器IP或域名后面加上/info.php例如http://你的服务器IP/info.php。如果一切正常你会看到一个详细的PHP配置信息页面其中包含了PHP版本、已加载的模块如mysqli, pdo_mysql, opcache等信息。这是LNMP环境搭建成功的标志重要安全步骤验证成功后务必立即删除这个info.php文件因为它会暴露服务器敏感信息。sudo rm /var/www/html/info.php4.2 测试PHP连接MySQL数据库创建一个测试数据库连接的PHP文件sudo vim /var/www/html/test_db.php写入以下内容将YourStrongPassword123!替换为你之前为webuser设置的密码?php $servername localhost; $username webuser; $password YourStrongPassword123!; $dbname mywebsite; // 创建连接 $conn new mysqli($servername, $username, $password, $dbname); // 检测连接 if ($conn-connect_error) { die(连接失败: . $conn-connect_error); } echo 连接MySQL数据库成功; $conn-close(); ?在浏览器访问http://你的服务器IP/test_db.php。如果页面显示“连接MySQL数据库成功”说明PHP通过MySQLi扩展连接数据库正常。同样测试完成后删除该文件sudo rm /var/www/html/test_db.php4.3 部署一个实际应用以WordPress为例理论验证通过我们来部署一个真正的PHP应用比如最流行的WordPress博客系统。下载并解压WordPresscd /var/www/html sudo wget https://wordpress.org/latest.tar.gz sudo tar -zxvf latest.tar.gz sudo mv wordpress/* . sudo rm -rf wordpress latest.tar.gz sudo chown -R nginx:nginx /var/www/html为WordPress创建数据库如果之前没创建 按照3.1节第4步的方法登录MySQL创建一个新的数据库例如wordpress_db和用户并授予权限。配置WordPress 浏览器访问你的服务器IP会进入WordPress著名的“五分钟安装”页面。根据提示输入你刚才创建的数据库名、用户名、密码数据库主机通常是localhost即可完成安装。注意事项部署真实应用后务必根据应用要求调整/var/www/html目录的文件权限。通常wp-content/uploads这类上传目录需要可写权限但为了安全应遵循最小权限原则只给必要的目录写权限。5. 性能调优与安全加固要点环境跑起来只是第一步要让其稳定、高效、安全地运行还需要进行一些调优和加固。5.1 PHP-FPM进程管理优化PHP-FPM的进程池配置对性能影响巨大。编辑/usr/local/php8.2/etc/php-fpm.d/www.confpm dynamic # 动态进程管理最常用 pm.max_children 50 # 最大子进程数根据内存计算总内存 / 单个PHP进程平均内存占用 pm.start_servers 5 # 启动时的子进程数 pm.min_spare_servers 5 # 空闲进程的最小数目 pm.max_spare_servers 35 # 空闲进程的最大数目 pm.max_requests 500 # 每个子进程处理多少请求后重启防止内存泄漏计算pm.max_children假设服务器有2G内存一个PHP-FPM进程平均占用30M那么max_children大约为2000M / 30M ≈ 66保守点可以设为50。你需要通过监控工具如htop观察实际内存占用来调整。5.2 Nginx基础性能优化编辑/usr/local/nginx/conf/nginx.conf在http块内增加或修改以下参数http { ... # 隐藏Nginx版本号增加安全性 server_tokens off; # 客户端请求体最大大小上传文件时需要调整 client_max_body_size 20m; # 开启高效文件传输模式 sendfile on; tcp_nopush on; tcp_nodelay on; # 连接超时时间 keepalive_timeout 65; # Gzip压缩配置减少传输体积 gzip on; gzip_min_length 1k; gzip_comp_level 2; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xmlrss text/javascript; ... }5.3 Opcache加速配置PHP Opcache是性能提升的神器。编辑/usr/local/php8.2/etc/php.ini找到[opcache]部分确保以下配置已启用并合理设置[opcache] opcache.enable1 opcache.memory_consumption128 ; 分配给OpCache的内存大小(MB)根据服务器内存调整64-256均可 opcache.interned_strings_buffer8 opcache.max_accelerated_files10000 ; 最大缓存文件数建议设大一些 opcache.revalidate_freq60 ; 检查脚本时间戳是否有更新的周期(秒)生产环境可设为0但更新代码后需手动重启PHP-FPM opcache.fast_shutdown1修改后需要重启PHP-FPMsudo systemctl restart php8.2-fpm。5.4 基础安全设置修改MySQL默认端口可选但推荐编辑/etc/my.cnf在[mysqld]部分添加port3307或其他非3306端口并重启MySQL。同时防火墙和安全组要放行新端口。限制PHP危险函数在php.ini中找到disable_functions添加如exec, system, shell_exec, passthru等函数防止代码执行漏洞被利用。disable_functions exec,system,shell_exec,passthru,proc_open,phpinfoNginx目录权限控制确保网站根目录的权限正确静态文件由Nginx直接处理PHP文件交给FPM。在Nginx配置中对上传目录等可写目录进行额外的限制禁止执行PHP。location ~* /uploads/.*\.php$ { deny all; }6. 日常运维与故障排查实录环境部署好之后日常维护和问题排查是必备技能。6.1 服务管理常用命令# 查看服务状态 sudo systemctl status nginx sudo systemctl status php8.2-fpm sudo systemctl status mysqld # 启动/停止/重启服务 sudo systemctl start/stop/restart nginx sudo systemctl start/stop/restart php8.2-fpm sudo systemctl start/stop/restart mysqld # 查看服务日志排查问题最重要 sudo tail -f /usr/local/nginx/logs/error.log # Nginx错误日志 sudo tail -f /usr/local/php8.2/var/log/php-fpm.log # PHP-FPM日志 sudo tail -f /var/log/mysqld.log # MySQL错误日志 # 也可以查看系统日志 sudo journalctl -u nginx -f6.2 常见问题与解决方案速查表问题现象可能原因排查步骤与解决方案访问网站显示“502 Bad Gateway”Nginx无法连接到PHP-FPM。1. 检查PHP-FPM服务是否运行systemctl status php8.2-fpm。2. 检查Nginx配置中fastcgi_pass指向的地址和端口默认127.0.0.1:9000是否与PHP-FPM配置文件(www.conf)中的listen一致。3. 检查SELinuxCentOS或AppArmorUbuntu是否阻止了连接可临时禁用测试或配置正确策略。访问网站显示“403 Forbidden”权限不足。1. 检查网站根目录如/var/www/html的所有者和权限。Nginx进程用户nginx必须有读取权限。ls -la /var/www/html。2. 检查目录索引文件如index.php是否存在。3. 检查Nginx配置中root指令路径是否正确。访问.php文件直接下载不执行PHP未正确解析。1. Nginx配置中缺少或错误配置了处理.php的location块。2.fastcgi_param SCRIPT_FILENAME参数错误应设置为$document_root$fastcgi_script_name。3. PHP-FPM未运行。MySQL连接失败提示“Access denied”用户名、密码错误或主机权限问题。1. 确认在PHP代码或应用配置中使用的数据库用户名、密码、主机名localhost是否正确。2. 登录MySQL检查用户是否有从localhost连接的权限SELECT host, user FROM mysql.user;。3. 如果是远程连接检查用户是否有从特定IP或%任何主机连接的权限并检查防火墙。网站访问速度慢资源不足或配置不当。1. 使用top或htop命令查看CPU、内存使用率。2. 检查PHP-FPM进程数是否足够pm.max_children是否频繁创建新进程。3. 检查MySQL慢查询日志。4. 确认Opcache已启用并生效在phpinfo()页面查看。上传文件大小受限Nginx或PHP配置限制了请求体大小。1. 在Nginx配置的http或server块中增加client_max_body_size 50m;例如调整为50M。2. 在PHP配置文件php.ini中修改upload_max_filesize和post_max_size的值并重启PHP-FPM。6.3 日志分析实战日志是排障的生命线。当出现问题时第一时间查看相关错误日志。Nginx访问日志/usr/local/nginx/logs/access.log记录了所有HTTP请求可以分析流量、排查恶意请求。Nginx错误日志/usr/local/nginx/logs/error.log记录了Nginx运行中的错误如权限问题、配置错误、上游PHP-FPM连接失败等。PHP-FPM错误日志/usr/local/php8.2/var/log/php-fpm.log记录了PHP-FPM进程管理相关的错误。PHP应用错误可以在php.ini中配置error_log路径并设置log_errors On将PHP脚本本身的错误记录到指定文件。一个典型的排障流程用户报错 → 查看浏览器具体错误代码502/500/404→ 查看Nginx错误日志 → 根据日志线索如“connect() failed”→ 检查PHP-FPM状态和配置 → 查看PHP-FPM日志 → 定位到具体问题如脚本语法错误、权限错误。最后再分享一个我常用的快速检查服务端口的小技巧sudo netstat -tlnp | grep -E ‘(:80|:3306|:9000)’。这个命令可以一眼看到Nginx(80)、MySQL(3306)、PHP-FPM(9000)的端口是否在正常监听对于快速判断服务状态非常有用。环境搭建不是一劳永逸的事根据实际访问量和应用特点持续观察日志、监控资源并微调配置才能让这套LNMP环境发挥出最佳性能。