还未起名 發表於 2025-12-10 10:30:13

利用Docker Compose部署多容器LNMP环境的实战步骤

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">1. 实战概述</a></li><li><a href="#_label1">2. 实战步骤</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_0">2.1 创建项目目录</a></li><li><a href="#_lab2_1_1">2.2 准备nginx配置文件</a></li><ul class="third_class_ul"><li><a href="#_label3_1_1_0">2.2.1 创建nginx容器</a></li><li><a href="#_label3_1_1_1">2.2.2 拷贝nginx配置文件到当前目录</a></li><li><a href="#_label3_1_1_2">2.2.3 停止并删除nginx容器</a></li><li><a href="#_label3_1_1_3">2.2.4 修改nginx配置文件</a></li></ul><li><a href="#_lab2_1_2">2.3 准备测试网页文件</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_1_3">2.4 准备php的Dockerfile文件</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_1_4">2.5 编写Docker编排配置文件</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_1_5">2.6 构建LNMP项目</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_1_6">2.7 测试LNMP项目</a></li><ul class="third_class_ul"><li><a href="#_label3_1_6_4">2.7.1 创建数据库连接</a></li><li><a href="#_label3_1_6_5">2.7.2 运行数据库脚本</a></li><li><a href="#_label3_1_6_6">2.7.3 查看数据表</a></li><li><a href="#_label3_1_6_7">2.7.4 准备图片文件</a></li><li><a href="#_label3_1_6_8">2.7.5 创建显示商品页面</a></li><li><a href="#_label3_1_6_9">2.7.6 重新构建LNMP项目</a></li><li><a href="#_label3_1_6_10">2.7.7 访问页面</a></li></ul><li><a href="#_lab2_1_7">2.8 停止并删除LNMP项目</a></li><ul class="third_class_ul"></ul></ul><li><a href="#_label2">3. 实战总结</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>1. 实战概述</h2>
<ul><li>本实战基于 Docker Compose 搭建 LNMP 开发环境,通过自定义 PHP-FPM 镜像安装 MySQL 扩展,配置 Nginx 反向代理 PHP 请求,导入商品数据并创建 <code>showProducts.php</code> 页面,成功实现商品信息的表格化展示,完整验证了 Web 服务、动态脚本与数据库的协同工作。</li></ul>
<p class="maodian"><a name="_label1"></a></p><h2>2. 实战步骤</h2>
<p class="maodian"><a name="_lab2_1_0"></a></p><h3>2.1 创建项目目录</h3>
<p>执行命令:<code>mkdir lnmp</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220663.png" /></p>
<p>执行命令:<code>cd lnmp</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220636.png" /></p>
<p>执行命令:<code>mkdir wwwroot php-fpm</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220679.png" /></p>
<p class="maodian"><a name="_lab2_1_1"></a></p><h3>2.2 准备nginx配置文件</h3>
<p class="maodian"><a name="_label3_1_1_0"></a></p><h4>2.2.1 创建nginx容器</h4>
<p>执行命令:<code>docker run -dit --name hwnginx nginx</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220665.png" /></p>
<p class="maodian"><a name="_label3_1_1_1"></a></p><h4>2.2.2 拷贝nginx配置文件到当前目录</h4>
<p>执行命令:<code>docker cp hwnginx:/etc/nginx ./</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220633.png" /></p>
<p class="maodian"><a name="_label3_1_1_2"></a></p><h4>2.2.3 停止并删除nginx容器</h4>
<p>执行命令:<code>docker stop hwnginx</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220692.png" /></p>
<p>执行命令:<code>docker rm hwnginx</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220613.png" /></p>
<p class="maodian"><a name="_label3_1_1_3"></a></p><h4>2.2.4 修改nginx配置文件</h4>
<p>执行命令:<code>notepad nginx/conf.d/default.conf</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220799.png" /></p>
<div class="jb51code"><pre class="brush:plain;">server {
    listen       80;
    listen[::]:80;
    server_namelocalhost;
    #access_log/var/log/nginx/host.access.logmain;
    location / {
      root   /usr/share/nginx/html;
      indexindex.html index.htm;
    }
    #error_page404            /404.html;
    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504/50x.html;
    location = /50x.html {
      root   /usr/share/nginx/html;
    }
    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}
    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
      root                /var/www;
      fastcgi_pass   fpm:9000;
      fastcgi_indexindex.php;
      fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name;
      include      fastcgi_params;
    }
    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    denyall;
    #}
}</pre></div>
<p class="maodian"><a name="_lab2_1_2"></a></p><h3>2.3 准备测试网页文件</h3>
<p>执行命令:<code>notepad wwwroot\index.html</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220842.png" /></p>
<div class="jb51code"><pre class="brush:xhtml;">&lt;!DOCTYPE html&gt;
&lt;html lang="zh-CN"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;   
    &lt;title&gt;首页&lt;/title&gt;
&lt;/head&gt;
&lt;body style='text-align: center; background-color: antiquewhite'&gt;
    &lt;h1 style='color: red'&gt;欢迎访问Nginx页面~&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;</pre></div>
<p>执行命令:<code>notepad wwwroot\index.php</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220960.png" /></p>
<div class="jb51code"><pre class="brush:php;">&lt;?php
// 设置时区
date_default_timezone_set('Asia/Shanghai');
// 获取当前日期时间并格式化
$now = date('Y-m-d H:i:s');
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang="zh-CN"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;   
    &lt;title&gt;当前时间&lt;/title&gt;
&lt;/head&gt;
&lt;bodystyle='text-align: center; background-color: antiquewhite'&gt;
    &lt;h1 style='color: red'&gt;系统当前日期时间&lt;/h1&gt;
    &lt;pstyle='color: blue'&gt;&lt;?php echo htmlspecialchars($now); ?&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</pre></div>
<p>执行命令:<code>notepad wwwroot\db.php</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220975.png" /></p>
<div class="jb51code"><pre class="brush:xhtml;">&lt;!DOCTYPE html&gt;
&lt;html lang="zh-CN"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;title&gt;数据库连接测试&lt;/title&gt;
    &lt;style&gt;
      body {
            text-align: center;
            padding-top: 50px;
            font-family: Arial, sans-serif;
            background-color: antiquewhite
      }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;?php
      $link = mysqli_connect('mysql', 'root', '903213');
      if (!$link) {
            echo '&lt;h2 style="color:red;"&gt;❌ 数据库连接失败!&lt;/h2&gt;';
            exit;
      }
      echo '&lt;h2 style="color:green;"&gt;✅ 数据库连接成功!&lt;/h2&gt;';
      mysqli_close($link);
    ?&gt;
&lt;/body&gt;
&lt;/html&gt;</pre></div>
<p class="maodian"><a name="_lab2_1_3"></a></p><h3>2.4 准备php的Dockerfile文件</h3>
<ul><li>Docker官方php镜像没有安装mysql插件,无法连接mysql数据库,需要利用Dockerfile重新生成新镜像。从php:7.4-fpm开始构建,安装 <code>mysqli</code> 和 <code>pdo_mysql</code> 扩展。</li><li>执行命令:<code>notepad php-fpm\Dockerfile</code></li></ul>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220872.png" /></p>
<p class="maodian"><a name="_lab2_1_4"></a></p><h3>2.5 编写Docker编排配置文件</h3>
<p>执行命令:<code>notepad docker-compose.yml</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220996.png" /></p>
<div class="jb51code"><pre class="brush:plain;">services:
fpm:
    build: ./php-fpm
    container_name: fpm
    volumes:
      - ./wwwroot:/var/www
    ports:
      - "9000"
nginx:
    image: nginx
    container_name: nginx
    ports:
      - "8100:80"
    volumes:
      - ./wwwroot:/usr/share/nginx/html
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/conf.d:/etc/nginx/conf.d
    depends_on:
      - fpm
mysql:
    image: mysql:5.7
    container_name: mysql
    ports:
      - "3309:3306"
    environment:
      MYSQL_ROOT_PASSWORD: 903213
      MYSQL_DATABASE: lnmp
    volumes:
      - mysql_data:/var/lib/mysql
volumes:
mysql_data:</pre></div>
<p class="maodian"><a name="_lab2_1_5"></a></p><h3>2.6 构建LNMP项目</h3>
<p>执行命令:<code>docker-compose up -d</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220874.png" /></p>
<ul><li><strong>结果说明</strong>:执行 <code>docker-compose up -d</code> 成功启动 LNMP 环境,创建了默认网络和 MySQL 数据卷,依次启动 fpm、mysql 和 nginx 容器,服务运行正常,可访问 http://localhost:8100 进行测试。</li></ul>
<p class="maodian"><a name="_lab2_1_6"></a></p><h3>2.7 测试LNMP项目</h3>
<p class="maodian"><a name="_label3_1_6_4"></a></p><h4>2.7.1 创建数据库连接</h4>
<p>创建<code>LNMPMySQL</code>数据库连接</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220826.png" /></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220887.png" /></p>
<p class="maodian"><a name="_label3_1_6_5"></a></p><h4>2.7.2 运行数据库脚本</h4>
<p>运行数据库脚本<code>lnmp.sql</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010220919.png" /></p>
<p>单击【开始】按钮</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010221012.png" /></p>
<p class="maodian"><a name="_label3_1_6_6"></a></p><h4>2.7.3 查看数据表</h4>
<p>查看商品表</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010221010.png" /></p>
<p class="maodian"><a name="_label3_1_6_7"></a></p><h4>2.7.4 准备图片文件</h4>
<p>在<code>D:\docker_work\lnmp\wwwroot\images</code>里准备15张商品图片</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010221094.png" /></p>
<p class="maodian"><a name="_label3_1_6_8"></a></p><h4>2.7.5 创建显示商品页面</h4>
<p>在<code>D:\docker_work\lnmp\wwwroot</code>里创建<code>showProducts.php</code>文件</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010221016.jpg" /></p>
<div class="jb51code"><pre class="brush:xhtml;">&lt;!DOCTYPE html&gt;
&lt;html lang="zh-CN"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;商品列表&lt;/title&gt;
    &lt;style&gt;
      body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #f9f9f9;
            margin: 20px;
            color: #333;
      }
      h1 {
            text-align: center;
            color: #0066cc;
            margin-bottom: 30px;
      }
      table {
            width: 100%;
            border-collapse: collapse;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            background: white;
            overflow: hidden;
            border-radius: 8px;
      }
      th, td {
            padding: 12px 15px;
            text-align: left;
            border-bottom: 1px solid #ddd;
      }
      th {
            background-color: #0066cc;
            color: white;
            font-weight: bold;
      }
      tr:hover {
            background-color: #f1f1f1;
      }
      img {
            width: 80px;
            height: 80px;
            object-fit: cover;
            border-radius: 4px;
            vertical-align: middle;
      }
      .no-image {
            width: 80px;
            height: 80px;
            background-color: #eee;
            display: flex;
            align-items: center;
            justify-content: center;
            color: #999;
            font-size: 12px;
      }
      .price {
            color: #e63946;
            font-weight: bold;
      }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;商品列表&lt;/h1&gt;
&lt;?php
// 数据库连接配置
$host = 'mysql';
$user = 'root';
$pass = '903213';
$dbname = 'lnmp';
try {
    $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $user, $pass);
    $pdo-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    // 查询所有商品
    $stmt = $pdo-&gt;query("SELECT id, name, price, image, add_time FROM t_product");
    $products = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
    if (empty($products)) {
      echo "&lt;p style='text-align:center; color:#999;'&gt;暂无商品数据。&lt;/p&gt;";
    } else {
      echo "&lt;table&gt;";
      echo "&lt;thead&gt;";
      echo "&lt;tr&gt;";
      echo "&lt;th&gt;ID&lt;/th&gt;";
      echo "&lt;th&gt;商品名称&lt;/th&gt;";
      echo "&lt;th&gt;价格&lt;/th&gt;";
      echo "&lt;th&gt;图片&lt;/th&gt;";
      echo "&lt;th&gt;添加时间&lt;/th&gt;";
      echo "&lt;/tr&gt;";
      echo "&lt;/thead&gt;";
      echo "&lt;tbody&gt;";
      foreach ($products as $product) {
            echo "&lt;tr&gt;";
            echo "&lt;td&gt;{$product['id']}&lt;/td&gt;";
            echo "&lt;td&gt;{$product['name']}&lt;/td&gt;";
            echo "&lt;td class='price'&gt;¥{$product['price']}&lt;/td&gt;";
            echo "&lt;td&gt;";
            if (!empty($product['image'])) {
                echo "&lt;img src='{$product['image']}' alt='{$product['name']}'&gt;";
            } else {
                echo "&lt;div class='no-image'&gt;无图&lt;/div&gt;";
            }
            echo "&lt;/td&gt;";
            echo "&lt;td&gt;{$product['add_time']}&lt;/td&gt;";
            echo "&lt;/tr&gt;";
      }
      echo "&lt;/tbody&gt;";
      echo "&lt;/table&gt;";
    }
} catch (PDOException $e) {
    echo "&lt;p style='color:red;'&gt;数据库错误:" . htmlspecialchars($e-&gt;getMessage()) . "&lt;/p&gt;";
}
?&gt;
&lt;/body&gt;
&lt;/html&gt;</pre></div>
<p class="maodian"><a name="_label3_1_6_9"></a></p><h4>2.7.6 重新构建LNMP项目</h4>
<p>执行命令:<code>docker-compose up --build -d</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010221088.jpg" /></p>
<p class="maodian"><a name="_label3_1_6_10"></a></p><h4>2.7.7 访问页面</h4>
<p>访问<code>http://localhost:8100</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010221069.png" /></p>
<p>访问<code>http://localhost:8100/index.php</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010221035.png" /></p>
<p>访问<code>http://localhost:8100/db.php</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010221063.png" /></p>
<p>访问<code>http://localhost:8100/showProducts.php</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010221073.jpg" /></p>
<p class="maodian"><a name="_lab2_1_7"></a></p><h3>2.8 停止并删除LNMP项目</h3>
<p>执行命令:<code>docker-compose down</code></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121010221063.png" /></p>
<ul><li><strong>结果说明</strong>:执行 <code>docker-compose down</code> 成功停止并移除了 mysql、nginx、fpm 三个容器及默认网络 lnmp_default,彻底清理了 LNMP 环境,避免资源占用和配置冲突,为下次部署提供干净环境。</li></ul>
<p class="maodian"><a name="_label2"></a></p><h2>3. 实战总结</h2>
<ul><li>本次实战通过 Docker Compose 成功构建了完整的 LNMP(Nginx + MySQL + PHP-FPM)开发环境。从创建项目目录、提取并配置 Nginx 默认配置,到编写自定义 Dockerfile 安装 <code>mysqli</code> 和 <code>pdo_mysql</code> 扩展,确保 PHP 能正常连接数据库;通过导入 <code>lnmp.sql</code> 初始化商品数据,并在 <code>wwwroot</code> 中准备图片资源,最终实现 <code>showProducts.php</code> 页面以美观表格展示全部商品信息。整个流程涵盖了容器编排、服务协同、数据库操作与前端展示,验证了 LNMP 架构的完整性与可用性。环境可一键启动(<code>docker-compose up -d</code>)和清理(<code>docker-compose down</code>),具备良好的可移植性与复用性,适用于教学、开发与快速部署场景。</li></ul>
<p>到此这篇关于利用Docker Compose部署多容器LNMP环境的实战步骤的文章就介绍到这了,更多相关docker compose 部署lnmp内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
頁: [1]
查看完整版本: 利用Docker Compose部署多容器LNMP环境的实战步骤