我们相信:世界是美好的,你是我也是。 来玩一下解压小游戏吧!

如果出于测试目的的话,苏南大叔测试机上面的phpstudy还是很好用的。那么,本文中的搭建方式,更接近于实际的运维场景。使用docker拉取并运行对应的容器,配置一个自己的LNMP组合。通过Docker安装最新版的Nginx/PHP/MySQL,并将它们配置到同一个网络中。

苏南大叔:docker安装nginx和php,如何修改ng配置、安装php扩展? - docker-nginx-php
docker安装nginx和php,如何修改ng配置、安装php扩展?(图5-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。测试环境:win10docker@28.0.4mysql@5.7nginx@1.27.4php@8.4.6-fpm。对于文中出现的换行连接符,苏南大叔这边因为测试环境是win10,所以使用的是 ^,读者可以根据实际情况使用 \

前文回顾

本文的内容,基于如下几篇文字:

如果拉取过程中出错,请记得配置daemon.json中的registry-mirrors字段,例如:

{ 
  "registry-mirrors" : 
    [ 
      "https://docker.m.daocloud.io",
      "https://docker.xuanyuan.me", 
      "https://docker.1ms.run"
    ] 
}

准备工作

宿主机上的持久化目录,参考分布如下:

D:\data
├─mysql
│  ├─conf
│  ├─data
│  └─log
├─nginx
│  ├─conf
│  └─log
├─php
│  ├─etc
│  └─extensions
└─www

这里的d:/data/www这个目录,在phpnginx中,都进行了映射/var/www,是个双重目录映射。参考nginx配置这一段内容。

苏南大叔:docker安装nginx和php,如何修改ng配置、安装php扩展? - 目录结构
docker安装nginx和php,如何修改ng配置、安装php扩展?(图5-2)

NginxPHPMySQL 容器,在不暴漏端口的前提下,为了能够相互通信,苏南大叔需要将它们放在同一个Docker network中,这里暂定网络名称为sunan_network。参考文字:

docker pull nginx
docker pull php:8.4.6-fpm
docker pull mysql:5.7
docker network create sunan_network

端口映射,并不是说绝对不能使用,这个是看实际情况来定的。就本文来说,

  • mysql做了3306端口映射,这主要是因为要使用第三方客户端对它进行管理。
  • nginx做了888:80的端口影射,这主要是因为本来nginx也必须曝露端口,但是宿主机上存在着另外的80应用。
  • php没有做端口映射,9000端口通过统一的network进行内部使用。

苏南大叔:docker安装nginx和php,如何修改ng配置、安装php扩展? - 端口映射情况
docker安装nginx和php,如何修改ng配置、安装php扩展?(图5-3)

安装 mysql

运行MySQL容器,并设置必要的目录映射和端口映射:

if not exist d:/data/mysql/my.cnf echo. > d:/data/mysql/my.cnf
docker run -d ^
  --name mysql-container ^
  --restart always ^
  --network sunan_network ^
  -e MYSQL_ROOT_PASSWORD=root ^
  -e MYSQL_DATABASE=sunan_db ^
  -v d:/data/mysql/my.cnf:/etc/mysql/my.cnf ^
  -v d:/data/mysql/conf:/etc/mysql/conf.d ^
  -v d:/data/mysql/data:/var/lib/mysql ^
  -v d:/data/mysql/log:/var/log/mysql ^
  -p 3306:3306 ^
  mysql:5.7 --character-set-server=utf8 --collation-server=utf8_general_ci

参数说明

  • --network sunan_network: 将容器加入到 sunan_network 网络中。
  • -e MYSQL_ROOT_PASSWORD=root: 设置 MySQL 的 root 用户密码。
  • -e MYSQL_DATABASE=sunan_database: 创建一个名为 sunan_database 的数据库。
  • -v d:/data/mysql/data:/var/lib/mysql: 持久化 MySQL 数据。
  • -v d:/data/mysql/conf:/etc/mysql/conf.d: 映射 MySQL 配置文件目录。
  • -p 3306:3306: 将 MySQL 的 3306 端口映射到宿主机。
  • --character-set-server=utf8,位置很重要,放在前面就执行出错。并且不设置utf8的话,就会出现中文乱码等问题。
是的,苏南大叔准备使用第三方客户端连接这个mysql容器,所以做了3306端口映射。

安装 PHP

先准备持久化数据:

docker run -d --name php-container php:8.4.6-fpm
docker cp php-container:/usr/local/etc d:/data/php/
docker cp php-container:/usr/local/lib/php/extensions d:/data/php/extensions/
docker stop php-container
docker rm php-container

正式运行PHP容器,并设置目录映射:

docker run -d ^
  --name php-container ^
  --restart always ^
  --network sunan_network ^
  -v d:/data/www:/var/www ^
  -v d:/data/php/etc:/usr/local/etc  ^
  -v d:/data/php/extensions:/usr/local/lib/php/extensions  ^
  php:8.4.6-fpm

参数说明

  • --network sunan_network: 将容器加入到 sunan_network 网络中。
  • -v d:/data/www:/var/www: 映射 PHP 项目代码目录。
  • -v d:/data/php/etc:/usr/local/etc: 映射自定义的 PHP 配置文件。
这里的/var/www是个特殊的路径,在nginx配置中会做出映射。

进入 PHP 容器并安装扩展:

docker exec -it php-container bash

在容器内运行以下命令安装扩展:

docker-php-ext-install mysqli
docker-php-ext-install命令,这不就是pecl install命令么?退出当前状态的命令是手敲的exit
exit

安装完成后,重启 PHP 容器:

docker restart php-container

安装 Nginx

依旧是做些目录映射方面的准备:

docker run -d --name nginx-container nginx:latest
docker cp nginx-container:/etc/nginx/conf.d d:/data/nginx/conf
docker cp nginx-container:/etc/nginx/nginx.conf d:/data/nginx/nginx.conf
docker stop nginx-container
docker rm nginx-container

运行 Nginx 容器,并设置目录映射和端口映射:

docker run -d ^
  --name nginx-container ^
  --restart always ^
  --network sunan_network ^
  -v d:/data/nginx/nginx.conf:/etc/nginx/nginx.conf ^
  -v d:/data/nginx/conf:/etc/nginx/conf.d ^
  -v d:/data/nginx/log:/var/log/nginx ^
  -v d:/data/www:/var/www:rw ^
  -p 888:80 ^
  nginx:latest

参数说明

  • --network sunan_network: 将容器加入到 sunan_network 网络中。
  • -v d:/data/nginx/conf:/etc/nginx/conf.d: 映射 Nginx 配置文件目录。
  • -v d:/data/www:/var/www: 映射网站项目代码目录。
  • -p 888:80: 将 Nginx 的 80 端口映射到宿主机的 888 端口。
没映射到主机的80端口,原因是宿主机上还有个dify重要应用占用着80端口。

Nginx 配置

修改在 d:/data/nginx/conf 目录下的配置文件:default.conf

server {
    listen 80;
    server_name localhost;
    root /var/www;
    index index.php index.html;
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    location ~ \.php$ {
        # root /var/www;
        include fastcgi_params;
        fastcgi_pass php-container:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

苏南大叔:docker安装nginx和php,如何修改ng配置、安装php扩展? - 检查配置文件
docker安装nginx和php,如何修改ng配置、安装php扩展?(图5-4)

配置好之后,重启nginx。命令如下:

docker restart nginx-container

或者进入到容器内部执行reload

docker exec -it nginx-container nginx -s reload

这个nginx配置是成败的关键。和通常意义上的nginx配置是有所不同的。因为这个例子中,nginxphp实际上并不在一起,相互隔离的,但是又在同一个network下面,所以在fastcgi_pass的配置是:php-container:9000

在这个例子中,实际上还有一点可能会容易忽略,那就是:php-containernginx-container使用了同一个目录映射/var/www。那么,在配置nginx的时候,在location ~ \.php$中就少设置了一个root。实际上这个省略的rootphp那边的路径。但是,两者路径相同,所以即使忽略了也不会报错。

测试环境

d:/data/www 目录下创建一个 index.php 文件:

$servername = "mysql-container"; // MySQL 容器的名称
$username = "root";              // MySQL 用户名
$password = "root";              // MySQL 密码
$database = "sunan_db";          // 数据库名称
$conn = new mysqli($servername, $username, $password, $database);
if ($conn->connect_error) {
    die("连接失败: " . $conn->connect_error);
}
echo "成功连接到 MySQL 数据库!";
$result = $conn->query("SELECT VERSION() AS version");
if ($result) {
    $row = $result->fetch_assoc();
    echo "<br>MySQL 版本: " . $row['version'];
} else {
    echo "<br>无法获取 MySQL 版本信息";
}
$conn->close();

苏南大叔:docker安装nginx和php,如何修改ng配置、安装php扩展? - 命令行设置好的参数在这里使用
docker安装nginx和php,如何修改ng配置、安装php扩展?(图5-5)

访问下面的地址查看效果:

关于持久化

在这篇文字里面,
【1】mysql的相关目录,并没有事先建立临时容器。而nginxphp则选择了相反的方案,选择建立临时容器,docker cp之后再进行删除。选择这样的处理方式的主要原因是(这和容器自身的情况有很大关系,不能苛责,只能适应):
mysql的数据,是容器进入后,再生成的数据。所以,仅提供目录即可。而nginxphp,开局就要读取到正确的配置文件,否则容器不能启动。所以,要先准备好正确的配置文件。

【2】关于在docker cp和目录映射的过程中,路径结尾的/是否使用,是有很大的区别的。查看运行结果,仔细体会。

总结

这种docker部署的方式,非常适合开发和测试环境,能够快速搭建一个完整的Web开发环境。更多苏南大叔的docker经验文章,请点击:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   docker