尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

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

从零手动搭建LNMP环境:Nginx+MySQL+PHP实战部署与优化指南 1. 项目概述为什么是LNMP如果你刚接触服务器运维或者想自己搭个网站玩玩大概率会听到“LNMP”或者“LAMP”这两个词。简单说这就是一套用来跑动态网站比如WordPress博客、论坛、电商后台的软件组合。LAMP里的“A”是Apache而LNMP里的“N”就是Nginx。我为什么更推荐新手从LNMP开始原因很直接Nginx在处理高并发连接时资源占用更少配置语法也更清晰直观。对于个人项目、学习环境或者中小型网站LNMP组合在性能和易用性上找到了一个很好的平衡点。这个教程的目标就是带你从一台干净的Linux服务器我以CentOS 7为例但思路通用开始一步步手动安装、配置Nginx、MySQL和PHP最终让一个PHP网站跑起来。整个过程我会把每个命令的作用、每个配置项的含义以及我踩过的坑都讲清楚。你不需要有任何搭建经验只要会敲命令行跟着做就一定能成功。这比直接用一键安装包学到的多得多以后出了问题你才知道从哪里下手解决。2. 环境准备与基础配置在开始安装任何软件之前我们需要确保服务器处于一个干净、网络通畅的状态。这一步看似简单但基础打不牢后面会冒出各种奇怪的问题。2.1 系统更新与基础工具安装首先登录你的Linux服务器。无论是通过SSH工具连接云服务器还是在虚拟机里操作第一步都是更新系统软件包到最新版本。这能确保我们安装的软件依赖关系是最新的避免兼容性问题。sudo yum update -y sudo yum install -y wget vim bash-completion net-tools这里解释一下这几个工具wget用于从网络下载文件后面我们会用它下载Nginx和PHP的源码包。vim一个强大的文本编辑器。系统自带的vi也可以但vim功能更友好一些。bash-completion提供命令自动补全功能能极大提升操作效率。net-tools包含netstat等网络诊断工具方便我们查看服务端口是否正常监听。注意如果你的系统是Ubuntu或Debian系列包管理工具是apt-get上述命令需要替换为sudo apt update sudo apt upgrade -y和sudo apt install -y wget vim bash-completion net-tools。本教程以CentOS/RHEL系的yum为例但核心步骤和原理完全相通。2.2 关闭防火墙与SELinux仅用于学习环境在生产环境中防火墙和SELinux是必须严格配置的安全屏障。但为了排除网络和权限对学习过程的干扰我们暂时关闭它们让环境更纯粹。等你完全理解整套流程后再学习如何配置防火墙规则和SELinux策略。# 临时关闭防火墙 sudo systemctl stop firewalld # 禁止防火墙开机自启 sudo systemctl disable firewalld # 临时关闭SELinux sudo setenforce 0 # 永久关闭SELinux需要重启生效 sudo sed -i s/SELINUXenforcing/SELINUXdisabled/g /etc/selinux/config重要提醒这仅适用于本地测试或纯粹的学习环境。如果你的服务器有公网IP并且准备长期运行在完成所有配置后必须重新开启防火墙并只开放必要的端口如80、443同时建议在理解的基础上配置SELinux或将其设置为宽容模式(permissive)。3. 核心组件安装与配置接下来我们将按照Nginx - MySQL - PHP的顺序安装。这个顺序是有讲究的先安装Web服务器Nginx和数据库MySQL最后安装处理动态脚本的引擎PHP并在最后统一配置它们之间的协作关系。3.1 安装并配置NginxNginx官方提供了稳定的Yum源这比编译安装更简单也便于后续升级。# 1. 安装EPEL源Extra Packages for Enterprise Linux sudo yum install -y epel-release # 2. 安装Nginx sudo yum install -y nginx # 3. 启动Nginx并设置开机自启 sudo systemctl start nginx sudo systemctl enable nginx安装完成后打开浏览器输入你的服务器IP地址。如果看到“Welcome to nginx!”的页面说明Nginx已经成功安装并运行。核心配置文件解析 Nginx的主配置文件是/etc/nginx/nginx.conf但通常我们不在这个文件里直接修改站点配置。最佳实践是在/etc/nginx/conf.d/目录下为每个网站创建一个独立的.conf配置文件。这样结构清晰管理方便。我们先来看一个最简单的PHP站点配置。创建一个新文件例如/etc/nginx/conf.d/myphp.confserver { listen 80; server_name localhost; # 这里可以改成你的域名或IP # 网站根目录我们稍后会创建 root /usr/share/nginx/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; } # 禁止访问.ht开头的隐藏文件通常是Apache的配置对Nginx无用 location ~ /\.ht { deny all; } }配置完成后一定要测试配置文件语法是否正确然后重载Nginx使配置生效sudo nginx -t sudo systemctl reload nginx实操心得nginx -t命令是救星。任何时候修改完配置先运行它检查语法确认无误后再reload。直接restart万一配置有错会导致Nginx服务停止网站就无法访问了。3.2 安装并配置MySQL (MariaDB)在Linux发行版中MySQL通常被其分支MariaDB所替代两者完全兼容且MariaDB在开源社区更活跃。我们安装MariaDB。# 1. 添加MariaDB的官方Yum源以10.5版本为例可自行替换为其他稳定版 sudo tee /etc/yum.repos.d/MariaDB.repo EOF [mariadb] name MariaDB baseurl http://yum.mariadb.org/10.5/centos7-amd64 gpgkeyhttps://yum.mariadb.org/RPM-GPG-KEY-MariaDB gpgcheck1 EOF # 2. 安装MariaDB服务器和客户端 sudo yum install -y MariaDB-server MariaDB-client # 3. 启动并设置开机自启 sudo systemctl start mariadb sudo systemctl enable mariadb安装完成后运行一个重要的安全脚本sudo mysql_secure_installation这个脚本会引导你完成以下设置请务必认真操作设置root密码这是数据库最高权限用户的密码必须设置一个强密码并牢记。移除匿名用户输入Y删除任何可以从本地主机匿名登录的账户。禁止root远程登录输入Y。这意味着root用户只能从服务器本机登录极大增强了安全性。后续管理可以通过创建专用管理用户并授权来实现。删除测试数据库输入Y移除名为test的数据库。立即重载权限表输入Y使上述所有安全设置生效。基础数据库操作 现在你可以登录MySQL创建一个用于网站的新数据库和用户。# 使用root用户登录MySQL密码是上一步设置的 mysql -u root -p # 登录成功后进入MySQL命令行执行以下SQL语句 -- 创建一个名为mywebsite的数据库字符集推荐使用utf8mb4以支持完整的UTF-8如表情符号 CREATE DATABASE mywebsite CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 创建一个用户webuser并设置密码请将YourPassword123!替换成你自己的强密码 CREATE USER webuserlocalhost IDENTIFIED BY YourPassword123!; -- 授予webuser用户对mywebsite数据库的所有权限 GRANT ALL PRIVILEGES ON mywebsite.* TO webuserlocalhost; -- 刷新权限使授权立即生效 FLUSH PRIVILEGES; -- 退出MySQL命令行 EXIT;注意事项数据库用户webuserlocalhost中的localhost限制了这个用户只能从服务器本机连接。这是安全的因为PHP和MySQL安装在同一台服务器上。如果你的Web应用和数据库是分离的则需要将localhost替换为Web服务器的IP地址或%允许任何主机连接不推荐。3.3 编译安装PHP为什么选择编译安装而不是用Yum直接安装因为Yum源中的PHP版本可能较旧且扩展模块不灵活。编译安装可以让我们自定义PHP版本和所需的扩展获得更好的性能和控制力。这里我们以PHP 7.4为例。# 1. 安装编译所需的依赖库 sudo yum install -y gcc gcc-c make libxml2-devel openssl-devel curl-devel libjpeg-devel libpng-devel freetype-devel libzip-devel # 2. 下载PHP源码包以7.4.33为例可前往官网获取最新稳定版链接 cd /usr/local/src sudo wget https://www.php.net/distributions/php-7.4.33.tar.gz sudo tar -zxvf php-7.4.33.tar.gz cd php-7.4.33 # 3. 配置编译选项 # 这一步是关键--prefix指定安装目录--with-fpm-user/group指定PHP-FPM进程运行的用户/组--enable-fpm启用PHP-FPM。 # 其他--with-xxx选项是启用你需要的扩展如MySQL支持mysqli, pdo_mysql、GD图像处理库等。 sudo ./configure \ --prefix/usr/local/php \ --with-config-file-path/usr/local/php/etc \ --enable-fpm \ --with-fpm-usernginx \ --with-fpm-groupnginx \ --with-mysqli \ --with-pdo-mysql \ --with-openssl \ --with-curl \ --with-gd \ --with-jpeg \ --with-png-dir \ --with-freetype \ --with-zlib \ --with-libzip \ --enable-mbstring \ --enable-xml # 4. 编译并安装此过程较慢取决于服务器性能 sudo make sudo make install # 5. 复制配置文件 sudo cp php.ini-production /usr/local/php/etc/php.ini sudo cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf sudo cp /usr/local/php/etc/php-fpm.d/www.conf.default /usr/local/php/etc/php-fpm.d/www.conf配置PHP-FPM PHP-FPM (FastCGI Process Manager) 是PHP的进程管理器Nginx通过FastCGI协议与它通信。我们需要编辑其配置文件/usr/local/php/etc/php-fpm.d/www.conf确保其用户/组与Nginx运行用户一致这样才能有权限读写Web目录下的文件。sudo vim /usr/local/php/etc/php-fpm.d/www.conf找到以下两行并进行修改; 将用户和组从默认的apache改为nginx user nginx group nginx创建Systemd服务文件方便管理sudo tee /usr/lib/systemd/system/php-fpm.service EOF [Unit] DescriptionThe PHP FastCGI Process Manager Afternetwork.target [Service] Typeforking PIDFile/usr/local/php/var/run/php-fpm.pid ExecStart/usr/local/php/sbin/php-fpm --nodaemonize --fpm-config /usr/local/php/etc/php-fpm.conf ExecReload/bin/kill -USR2 \$MAINPID PrivateTmptrue [Install] WantedBymulti-user.target EOF启动PHP-FPM并设置开机自启sudo systemctl daemon-reload sudo systemctl start php-fpm sudo systemctl enable php-fpm4. 整合测试与项目部署所有组件都安装配置好了现在需要把它们串联起来并部署一个真实的PHP应用进行测试。4.1 创建测试文件并验证环境首先在Nginx的网站根目录创建一个经典的info.php文件来探针。sudo tee /usr/share/nginx/html/info.php EOF ?php phpinfo(); ? EOF修改这个文件的权限确保Nginx用户能读取它sudo chown nginx:nginx /usr/share/nginx/html/info.php sudo chmod 644 /usr/share/nginx/html/info.php现在打开浏览器访问http://你的服务器IP/info.php。如果一切配置正确你将看到一个详细的PHP信息页面里面包含了PHP版本、已加载的扩展尤其是mysqli和pdo_mysql以及服务器环境信息。如果看到这个页面恭喜你LNMP环境的核心部分已经打通了。4.2 部署一个简单的PHP应用以TodoList为例光有探针还不够我们部署一个需要连接数据库的简单应用。这里用一个极简的待办事项列表Todo List作为例子。创建应用目录和文件# 创建一个专门的应用目录 sudo mkdir -p /usr/share/nginx/html/todo sudo chown -R nginx:nginx /usr/share/nginx/html/todo cd /usr/share/nginx/html/todo创建数据库表结构 登录MySQL为你之前创建的mywebsite数据库创建一张表。mysql -u root -p USE mywebsite; CREATE TABLE todos ( id INT AUTO_INCREMENT PRIMARY KEY, task VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); EXIT;编写PHP应用代码 创建index.php文件?php // 数据库连接配置 $host localhost; $dbname mywebsite; $username webuser; $password YourPassword123!; // 替换成你设置的密码 try { $pdo new PDO(mysql:host$host;dbname$dbname;charsetutf8mb4, $username, $password); $pdo-setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { die(数据库连接失败: . $e-getMessage()); } // 处理添加新任务 if ($_SERVER[REQUEST_METHOD] POST !empty($_POST[task])) { $task trim($_POST[task]); $stmt $pdo-prepare(INSERT INTO todos (task) VALUES (?)); $stmt-execute([$task]); header(Location: . $_SERVER[PHP_SELF]); // 重定向防止重复提交 exit; } // 处理删除任务 if (isset($_GET[delete])) { $id (int)$_GET[delete]; $stmt $pdo-prepare(DELETE FROM todos WHERE id ?); $stmt-execute([$id]); header(Location: . $_SERVER[PHP_SELF]); exit; } // 获取所有任务 $stmt $pdo-query(SELECT * FROM todos ORDER BY created_at DESC); $todos $stmt-fetchAll(PDO::FETCH_ASSOC); ? !DOCTYPE html html head title简易Todo List/title stylebody{font-family: sans-serif; max-width:600px; margin:40px auto;} .task{margin:10px 0;}/style /head body h1我的待办事项/h1 form methodPOST input typetext nametask placeholder输入新任务... required stylewidth:70%; padding:8px; button typesubmit stylepadding:8px 15px;添加/button /form hr ul ?php foreach ($todos as $todo): ? li classtask ?php echo htmlspecialchars($todo[task]); ? small(添加于: ?php echo $todo[created_at]; ?)/small a href?delete?php echo $todo[id]; ? onclickreturn confirm(确定删除) stylecolor:red; margin-left:15px;[删除]/a /li ?php endforeach; ? ?php if (empty($todos)): ? liem暂无待办事项。/em/li ?php endif; ? /ul /body /html配置Nginx站点 为这个Todo应用单独创建一个Nginx配置/etc/nginx/conf.d/todo.confserver { listen 80; server_name localhost; # 或你的域名 root /usr/share/nginx/html/todo; index index.php; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }测试并重载Nginx配置sudo nginx -t sudo systemctl reload nginx现在访问http://你的服务器IP/todo你应该能看到一个可以添加和删除任务的简易待办事项列表。这证明你的LNMP环境已经完全正常工作PHP能够成功连接并操作MySQL数据库。5. 性能调优与安全加固基础环境跑通只是第一步要让其稳定、安全、高效地运行还需要进行一些基础的调优和加固。5.1 PHP-FPM进程管理优化PHP-FPM的进程池配置直接影响性能和资源消耗。编辑/usr/local/php/etc/php-fpm.d/www.conf关注以下参数pm dynamic ; 进程管理方式。dynamic是动态模式最常用。 pm.max_children 50 ; 最大子进程数。根据服务器内存设置每个PHP进程约占用20-50M内存50个进程大约需要1G-2.5G内存。 pm.start_servers 5 ; 启动时的子进程数。 pm.min_spare_servers 5 ; 空闲进程的最小数量。 pm.max_spare_servers 35 ; 空闲进程的最大数量。 pm.max_requests 500 ; 每个子进程处理多少请求后重启有助于防止内存泄漏。调整原则对于内存较小的服务器如1Gpm.max_children可设为20-30。观察服务器的内存使用情况 (free -m) 和PHP-FPM状态 (sudo systemctl status php-fpm) 进行动态调整。5.2 MySQL基础优化编辑MySQL配置文件/etc/my.cnf或/etc/my.cnf.d/server.cnf在[mysqld]段落下添加一些基础优化参数[mysqld] # 禁用DNS反向解析加快连接速度 skip-name-resolve # 设置默认字符集 character-set-serverutf8mb4 collation-serverutf8mb4_unicode_ci # InnoDB缓冲池大小对于专用数据库服务器可设置为物理内存的50%-70% innodb_buffer_pool_size 256M # 最大连接数根据应用需求调整 max_connections 100修改配置后重启MySQL服务sudo systemctl restart mariadb5.3 文件权限与目录安全这是安全的重中之重。原则是最小权限原则。代码目录Web目录如/usr/share/nginx/html的所有者应为nginx用户权限设置为755目录和644文件确保Nginx有读权限但一般没有写权限。上传目录如果应用有文件上传功能如头像应单独设置一个目录如uploads并将其权限设置为755所有者仍为nginx。切勿将整个网站根目录设置为777。配置文件包含数据库密码等敏感信息的配置文件如config.php应放在Web根目录之外并通过PHP的include_path引入。如果必须在Web目录下权限应设为600并确保.php后缀防止被直接下载。5.4 重新启用防火墙重要学习完成后务必重新启用防火墙并只开放必要的端口。sudo systemctl start firewalld sudo systemctl enable firewalld # 开放HTTP(80)和HTTPS(443)端口SSH(22)端口通常默认已开放 sudo firewall-cmd --permanent --add-servicehttp sudo firewall-cmd --permanent --add-servicehttps sudo firewall-cmd --reload # 查看当前开放的端口 sudo firewall-cmd --list-all6. 故障排查与日常维护即使按照教程一步步来也可能会遇到问题。这里列出几个最常见的问题和排查思路。6.1 常见问题速查表问题现象可能原因排查命令/步骤访问IP显示“502 Bad Gateway”1. PHP-FPM服务未运行。2. Nginx配置中fastcgi_pass地址/端口错误。3. PHP-FPM与Nginx用户/组不一致导致权限问题。1.sudo systemctl status php-fpm2. 检查Nginx配置中fastcgi_pass是否为127.0.0.1:9000。3. 检查/usr/local/php/etc/php-fpm.d/www.conf中的user和group是否与Nginx运行用户通常是nginx一致。访问.php文件直接下载而不执行Nginx未正确配置PHP处理。1. 检查Nginx站点配置中是否有location ~ \.php$ { ... }块。2. 检查该块内fastcgi_param SCRIPT_FILENAME是否正确指向了$document_root$fastcgi_script_name。3. 执行sudo nginx -t检查语法。PHP页面空白或报错“No input file specified.”SCRIPT_FILENAME路径错误或PHP文件不存在。1. 确认root目录设置正确。2. 确认.php文件存在于root目录下。3. 在Nginx配置的location ~ \.php$块内添加一行fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;。数据库连接失败1. 数据库服务未启动。2. PHP未安装pdo_mysql或mysqli扩展。3. 数据库用户名、密码、主机名或数据库名错误。4. 数据库用户权限不足或未授权从本地连接。1.sudo systemctl status mariadb2. 在info.php页面中查找“pdo_mysql”和“mysqli”扩展是否已启用。3. 仔细核对PHP代码中的连接参数。4. 登录MySQL执行SHOW GRANTS FOR webuserlocalhost;查看权限。修改Nginx/PHP配置后不生效服务未重载。1. Nginx:sudo nginx -t sudo systemctl reload nginx2. PHP-FPM:sudo systemctl reload php-fpm6.2 日志查看你的第一道诊断工具当出现问题时查看日志是定位问题最快的方法。Nginx错误日志sudo tail -f /var/log/nginx/error.logNginx访问日志sudo tail -f /var/log/nginx/access.logPHP-FPM错误日志在/usr/local/php/etc/php-fpm.d/www.conf中查看catch_workers_output和error_log设置通常位于/usr/local/php/var/log/php-fpm.log。PHP错误日志在/usr/local/php/etc/php.ini中设置log_errors On和error_log /var/log/php_errors.log。6.3 日常维护命令查看服务状态sudo systemctl status nginxsudo systemctl status php-fpmsudo systemctl status mariadb查看服务器资源占用tophtopfree -mdf -h查看端口监听情况sudo netstat -tlnp | grep -E (:80|:3306|:9000)手动搭建LNMP环境的过程就像亲手组装一台精密仪器。虽然步骤繁琐但每一步都让你对Web应用的运行基石有了更深刻的理解。下次再遇到环境问题你就不再是束手无策而是可以冷静地查看日志、分析配置、逐步排错。这套环境足以支撑你运行绝大多数PHP开源项目接下来你可以尝试部署WordPress、ThinkPHP、Laravel等框架去探索更广阔的世界了。如果在实践中遇到本教程未覆盖的特定问题多利用搜索引擎关键词加上“CentOS 7”、“Nginx”、“PHP-FPM”社区里总有前辈踩过类似的坑。
返回列表