windows环境下用docker搭建php开发环境dnmp

news/2025/2/22 3:10:48

安装WSL


WSL即Linux子系统,比虚拟机占用资源少,安装的前提是系统必须是win10以上。

WSL的安装比较简单,网上有很多教程,例如:WSL简介与安装流程(Windows 下的 Linux 子系统)_wsl安装-CSDN博客,我这里就不多赘述了

安装DockerDesktop


官网下载:Docker Desktop: The #1 Containerization Tool for Developers | Docker

汉化包(可选):asxez/DockerDesktop-CN: Docker汉化 Docker中文版 Docker汉化包 DockerDesktop汉化 Docker Windows Docker MAC

修改镜像存储目录(可选):由于镜像比较大,为了不占用c盘用空间,可以设置修改镜像存储目录

下载dnmp


我们直接用github上star比较多的,虽然有点缺陷,很多东西文档上也没说,不过该有的都有,没有的我会补充

项目github地址:garymengcom/dnmp: Docker LNMP (Nginx, PHP7/PHP5, MySQL, Redis)

git clone https://github.com/garymengcom/dnmp.git

配置文件


1.复制配置文件

cd dnmp
copy env.sample .env
copy docker-compose.sample.yml docker-compose.yml

2.修改.env文件配置

  • 修改php代码目录,把SOURCE_DIR修改为你的php代码所在目录,默认是dnmp/www,假如我的是D:/wwwroot目录,则修改为

    SOURCE_DIR=D:/wwwroot
    
  • 增加php扩展,默认安装php扩展比较少,根据需要需要在对应的php配置中添加额外的扩展,如redis,exif,bcmath

  • 修改mysql端口、root密码

3.修改docker-compose.yml文件,把自己不需要的服务注释掉,需要的加上。例如:默认会同时安装mysql5mysql8,根据自己的需求,只保留其中一个;

4.默认配置文件都在services目录下对应的程序目录里面,保持默认即可

启动服务


docker-compose up -d

如果下载镜像的过程中报错网络问题无法下载,可以看下面的【更换镜像源】这一节解决,或者尝试手动执行docker pull 单独拉取镜像试试

等待镜像下载完成,容器运行了就可以了。如果安装了Docker Desktop,按照提示按v键可以跳转到 Docker Desktop中查看跑起来的服务

访问http://localhost即可访问到默认的网站

更换镜像源


如果启动服务过程中报下面的错,镜像无法下载,则需要更换docker镜像源

可以上网找一下当前可用的docker镜像源,例如:https://cloud.tencent.com/developer/article/2485043,然后在或DockerDesktop的配置中增加镜像配置registry-mirrors,镜像地址自己找最新可用的地址

{
  "builder": {
    "gc": {
      "defaultKeepStorage": "20GB",
      "enabled": true
    }
  },
  "experimental": false,
  "registry-mirrors": [
    "https://docker.1ms.run"
  ]
}

安装PHP扩展


参考官方文档即可:garymengcom/dnmp: Docker LNMP (Nginx, PHP7/PHP5, MySQL, Redis)

新建站点


默认有一个localhost网站,目录在dnmp\www\localhost,按照下面的步骤可以新建一个站点,以创建www.test-site.net为例

  • 1.创建nginx站点配置文件

    进入dnmp\services\nginx\conf.d目录,新建文件www.test-site.net.conf,文件内容如下(将www.test-site.net全部替换为你自己的域名即可, 注意修改fastcgi_pass配置项对应的php容器)

    server {
        server_name  www.test-site.net;
        listen       80;
    
        root   /www/www.test-site.net;
        index  index.php index.html index.htm;
        #charset koi8-r;
        
        access_log /dev/null;
        #access_log  /var/log/nginx/nginx.www.test-site.net.access.log  main;
        error_log  /var/log/nginx/nginx.www.test-site.net.error.log  warn;
        
        #error_page  404              /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
        # 注意修改fastcgi_pass中对应的php容器
        #
        location ~ [^/]\.php(/|$) {
            fastcgi_pass   php74:9000;
            include        fastcgi-php.conf;
            include        fastcgi_params;
        }
    
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }
    
  • 2.修改本地hosts文件,增加一条记录

    127.0.0.1 www.test-site.net
    
  • 3.新增php代码

    php代码目录(默认是dnmp\www)下新建站点目录dnmp\www\www.test-site.net,里面存放该站点的php文件

  • 4.重启nginx,浏览器访问http://www.test-site.net/即可,需要注意的是如果你开了代理可能会导致hosts文件映射失效!

  • 5.如果每个网站需要不同的php版本,那么需要启动对应版本的php容器并且网站的nginx配置文件中的fastcgi_pass配置项需要修改为对应的php版本

注意事项

如果项目是thinkphp或laravel等web框架,需要将www.test-site.net.conf配置中的root /www/www.test-site.net;修改为public目录,如:root /www/www.test-site.net/public,然后增加伪静态配置

Laravel伪静态:
location / {  
	try_files $uri $uri/ /index.php$is_args$query_string;  
}  


ThinkPHP5.x伪静态:
location / {
    try_files $uri $uri/ /index.php?$query_string;
}

ThinkPHP6.x伪静态:
location / {
    if (!-e $request_filename) {
        rewrite  ^(.*)$  /index.php?s=$1  last;
        break;
    }
}

SSL证书


  • 1.生成证书

    本地自签名证书推荐mkcert:Windows下安装mkcert_windows安装mkcert-CSDN博客

    生产环境免费证书推荐Let‘s Encrypt:[SSL]Let‘s Encrypt生成免费的SSL证书_let’s encrypt 证书-CSDN博客

    当然,也可以选择其他付费SSL证书,证书包括.crt.key格式的两个文件,在dnmp\services\nginx\ssl目录创建跟网站域名一致的文件夹,然后将两个证书文件放到文件夹里即可

  • 2.在对应站点的nginx配置文件最后增加下面这段配置,注意将证书路径替换为你的

    listen 443 ssl;
    ssl_certificate /ssl/www.test-site.net/www.test-site.net+2.pem;
    ssl_certificate_key /ssl/www.test-site.net/www.test-site.net+2-key.pem;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ALL:!DH:!EXPORT:!RC4:+HIGH:+MEDIUM:!LOW:!aNULL:!eNULL;
    
  • 3.重启nginx生效

    docker-compose restart nginx
    

php_275">解决dnmp环境下php运行慢问题

你有没有发现使用WSL+Docker这种方式运行php连输出简单的hello world都要4秒钟,为什么会这么慢???

  • 原因

    WSL2 的跨文件系统的io读写性能非常非常差,官方已经告诉了我们关键问题和解决方案:不要将项目挂载到 Windows 系统中,
    而是挂载到 WSL 文件系统中。

  • 思路

    1.参考文章 解决Docker使用WSL2项目运行慢的问题 | Laravel China 社区,将原本.env配置文件中的SOURCE_DIR路径(也就是windows与docker容器映射的目录)改为WSL路径,也就是windows与docker容器目录映射改为wsl与docker容器目录映射,然后进入WSL,在WSL中执行docker-compose up命令。然后把php代码复制一份到这个WSL目录中,这样就不存在跨文件系统读写问题了,再次访问docker中的php网站,快到飞起!!!但是又产生新的问题:代码文件怎么同步?用FTP有点麻烦,linux定时同步也很麻烦。。。

    2.不知道你发现没有,在DockerDesktop中勾选Enable integration with my default WSL distro的话,你的电脑中会多出一个Linux文件目录,你可以直接在windows下访问WSL中的文件。通过查询资料得知,在WSL中,/mnt目录是与windows的硬盘目录是连通的,也就是在WSL中也能直接读取到你在windows中的php代码目录!!!

  • 解决

    有了上面两个前提,那就好解决了,直接把WSL中/mnt代码目录(与windows中的代码目录相同)和docker容器的目录映射起来,按照下面两个步骤操作就可以了

    1.修改.env中的php代码目录SOURCE_DIR为WSL目录,例如我的代码目录为D盘下的D:\dnmp\www,那么就改为SOURCE_DIR=/mnt/d/dnmp/www/

    2.通过cmd进入WSL(直接输入wsl命令)然后在WSL中运行docker-compose up -d即可,就是这么简单。千万不要在windows下启动docker-compose, 因为windows下没有/mnt/d/dnmp/www目录,会映射失败。当然,第一次在WSL启动成功之后,也可以在dockerDesktop界面中直接点按钮一键启动!再次访问docker中的网站看看是不是快多了!

如果myql容器无法正常启动,请参考下面的【常见问题 · 在WSL中docker启动mysql容器失败】解决

自定义镜像


项目使用的镜像都是官方镜像,有时候会满足不了我们的需求,比如php扩展比较少,增加扩展之后如果要多机部署又要安装一次php扩展,非常不方便。目前可用的解决方法是打包并发布自己的镜像,然后修改dnmp\services目录下对应的程序Dockerfile文件中的镜像名称再执行docker-compose up

新增PHP版本


以新增PHP8.4为例

  • 1.在docker-compose.yml文件中复制一份PHP8.2的配置并替换为PHP8.4,注意先不要做目录映射,因为还没有默认的配置文件

    php84:
        build:
          context: ./services/php84
          args:
            DEBIAN_MIRROR_DOMAIN: deb.debian.org
            PHP_EXTENSIONS: "$PHP84_EXTENSIONS"
            TZ: "$TZ"
        container_name: php84
        expose:
          - 9501
        volumes:
          - ${SOURCE_DIR}:/www/:rw
          - ${PHP84_LOG_DIR}:/var/log/php
          - ${PHP84_DATA_COMPOSER}:/tmp/composer
        restart: always
        cap_add:
          - SYS_PTRACE
        networks:
          - default
    
  • 2.在.env文件中复制一份PHP8.2的配置并替换为PHP8.4,修改配置文件位置,注意将扩展删除,只保留curl即可,不然可能会安装报错

    #
    # PHP84
    #
    # Available PHP_EXTENSIONS:
    #
    # pdo_mysql,zip,pcntl,mysqli,mbstring,exif,bcmath,calendar,
    # sockets,gettext,shmop,sysvmsg,sysvsem,sysvshm,pdo_rebird,
    # pdo_dblib,pdo_oci,pdo_odbc,pdo_pgsql,pgsql,oci8,odbc,dba,
    # gd,intl,bz2,soap,xsl,xmlrpc,wddx,curl,readline,snmp,pspell,
    # recode,tidy,gmp,imap,ldap,imagick,sqlsrv,mcrypt,opcache,
    # redis,memcached,xdebug,swoole,pdo_sqlsrv,sodium,yaf,mysql,
    # amqp,mongodb,event,rar,ast,yac,yar,yaconf,msgpack,igbinary,
    # seaslog,varnish,xhprof,xlswriter,memcache,rdkafka,zookeeper,
    # psr,phalcon,sdebug,ssh2,yaml,protobuf,hprose
    #
    # You can let it empty to avoid installing any extensions,
    # or install multi plugins as:
    # PHP84_EXTENSIONS=pdo_mysql mysqli gd curl opcache
    # Note::that it is a space
    
    PHP84_VERSION=8.4.3
    PHP84_PHP_CONF_FILE_DEVELOPMENT=./services/php84/php.ini-development
    PHP84_PHP_CONF_FILE_PRODUCTION=./services/php84/php.ini-production
    PHP84_FPM_CONF_FILE=./services/php84/www.conf
    PHP84_LOG_DIR=./logs/php84
    PHP84_DATA_COMPOSER=./data/composer
    PHP84_EXTENSIONS=curl
    
  • 3.在dnmp项目中新建php84目录和Dockerfile文件

    cd service && mkdir php84
    cd php82 && copy Dockerfile ..\php84\
    

    编辑php84/Dockerfile,将里面的FROM php:8.2-fpm改为FROM php:8.4-fpm并保存

  • 4.在WSL中执行docker-compose up -d创建容器

  • 5.在WSL中执行下面的命令复制配置文件到宿主机

    首先查看php84容器/usr/local/etc目录下有什么配置文件

    然后将3个需要的文件复制到宿主机

    docker cp php84:/usr/local/etc/php/php.ini-development /mnt/d/dnmp/services/php84/php.ini-development
    docker cp php84:/usr/local/etc/php/php.ini-production /mnt/d/dnmp/services/php84/php.ini-production
    docker cp php84:/usr/local/etc/php-fpm.d/www.conf /mnt/d/dnmp/services/php84/php-fpm.conf
    
  • 6.修改docker-compose.yml目录映射配置文件,注意变量要跟.env文件中对应

    php84:
        build:
          context: ./services/php84
          args:
            DEBIAN_MIRROR_DOMAIN: deb.debian.org
            PHP_EXTENSIONS: "$PHP84_EXTENSIONS"
            TZ: "$TZ"
        container_name: php84
        expose:
          - 9501
        volumes:
          - ${SOURCE_DIR}:/www/:rw
          - ${PHP84_PHP_CONF_FILE_DEVELOPMENT}:/usr/local/etc/php/php.ini-development
          - ${PHP84_PHP_CONF_FILE_PRODUCTION}:/usr/local/etc/php/php.ini-production
          - ${PHP84_FPM_CONF_FILE}:/usr/local/etc/php-fpm.d/www.conf
          - ${PHP84_LOG_DIR}:/var/log/php
          - ${PHP84_DATA_COMPOSER}:/tmp/composer
        restart: always
        cap_add:
          - SYS_PTRACE
        networks:
          - default
    
  • 7.在WSL中删掉php84容器并重新创建

    docker rm php84
    docker-compose up -d
    

    到此新增PHP版本成功

常见问题


  • php编译失败

    php在编译过程中可能会遇到扩展安装报错导致编译失败

    可以尝试修改.env文件中的CONTAINER_PACKAGE_URL,这一行的上面有提供几个url,可以逐个尝试看看能不能解决。如果还不能解决,打开.env文件,在对应的PHP扩展中删除部分扩展,例如只保留curl扩展,其他扩展等容器跑起来后手动安装。

  • 在WSL中docker启动mysql容器失败

    mysql无法启动,查看日志发现报错没有权限[ERROR] Could not set file permission for ca-key.pem,原因是wsl.conf文件没有metadata信息,需要修改wsl的配置才能支持修改文件属性。进入WSL,然后编辑/etc/wsl.conf文件增加下面的配置信息,重启WSL即可

    [automount]
    enabled = true
    options = "metadata"
    mountFsTab = false
    

    在windows cmd下重启WSL

    # 关闭wsl
    wsl --shutdown
    # 启动并进入wsl
    wsl
    

    再次进入WSL执行docker-compose up -d即可正常启动容器

    参考文章:https://blog.csdn.net/x356982611/article/details/108732844


http://www.niftyadmin.cn/n/5861548.html

相关文章

rtpengine and redis

redis 用来在不同 rtpengine 实例之间同步会话信息 回头做做测试,看下到底怎么用 这里有几个链接: https://github.com/sipwise/rtpengine/wiki/Redis-keyspace-notifications https://kamailio.org/events/2020-KamailioWorldOnline/KW2020-YufeiTa…

【C++】:奇异递归模板模式

一、基本概念 奇异递归模板模式(Curiously Recurring Template Pattern, CRTP)是一种C++模板元编程技术,核心特征是子类将自己作为模板参数传递给基类。这使得基类能够在编译时获得子类的具体类型信息,从而实现静态多态、接口注入等高级功能。 二、核心机制与典型示例 2…

Ubuntu如何利用.ibd文件恢复MySQL数据?

## 背景:服务器中,MySQL程序坏了,也没有做定时备份的操作。为了是数据库恢复到最新的。 ## 方法:可以使用MySQL的 .ibd 文件恢复。(需要原数据库的表结构) ## 文件位置:在Ubuntu系统中&#x…

第4章 信息系统架构(三)

4.3 应用架构 应用架构的主要内容是规划出目标应用分层分域架构,根据业务架构规划目标应用域、应用组和目标应用组件,形成目标应用架构逻辑视图和系统视图。从功能视角出发,阐述应用组件各自及应用架构整体上,如何实现组织的高阶…

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_process_options

ngx_process_options 声明在 src\core\nginx.c static ngx_int_t ngx_process_options(ngx_cycle_t *cycle); 定义在 src\core\nginx.c static ngx_int_t ngx_process_options(ngx_cycle_t *cycle) {u_char *p;size_t len;if (ngx_prefix) {len ngx_strlen(ngx_prefix);p …

51单片机-按键

1、独立按键 1.1、按键介绍 轻触开关是一种电子开关,使用时,轻轻按开关按钮就可使开关接通,当松开手时,开关断开。 1.2、独立按键原理 按键在闭合和断开时,触点会存在抖动现象。P2\P3\P1都是准双向IO口,…

ssm121基于ssm的开放式教学评价管理系统+vue(源码+包运行+LW+技术指导)

项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问…

QT 建立一片区域某种颜色

绘制一个位于(50, 50)的200x200的红色矩形 #include "widget.h" #include "ui_widget.h" #include <QPainter>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);update(); }Widget::~Widget() {delete…