Laravel 是一套简洁、优雅的 PHP Web 开发框架 (PHP Web Framework)。

Laravel: https://laravel.com/
Laravel GitHub: https://github.com/laravel

1. 部署环境

    IP 地址(本地测试环境):192.168.0.10
    操作系统:Linux CentOS 7.9     
    Docker 版本: 20.10.7
    Docker Compose 版本: 2.6.1

    Nginx 目录:/home/docker/nginx
    MariaDB 目录:/home/docker/mysql
    Php 目录:/home/docker/php
    Laravel 目录:/home/docker/laravel

2. 创建 Dockerfile

    Docker pull 下载的 PHP 镜像,缺少需要的扩展,所以编写 Dockerfile 在本地生成需要的 PHP 镜像。

        $ cd /home/docker/laravel
        $ vim Dockerfile

FROM php:7.4-fpm

            RUN sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list
            RUN sed -i s@/security.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list

            RUN apt-get update && apt-get install -y zlib1g-dev libzip-dev

            RUN docker-php-ext-install pdo_mysql mysqli zip
            RUN docker-php-ext-enable pdo_mysql mysqli zip

            注:运行 sed 命令把 docker 容器的 apt 改成阿里源,zip 扩展依赖 zlib1g-dev 和 libzip-dev,所以 docker-php-ext-install 安装 zip 之前需要先安装这两个系统库 。

        $ docker build -t php:7.4-fpm-mysqli .

        $ docker images

            REPOSITORY   TAG              IMAGE ID       CREATED         SIZE
            php          7.4-fpm-mysqli   fbca0f9390a3   8 seconds ago   444MB
            php          7.4-fpm              cf71a2f33ec4   3 minutes ago    444MB

 

  可以通过 docker-php-ext-install 安装的常用扩展:

    bcmath bz2 calendar ctype curl dba dom enchant exif fileinfo filter ftp gd gettext gmp hash iconv imap interbase intl json ldap mbstring mysqli oci8 odbc opcache pcntl pdo pdo_dblib pdo_firebird pdo_mysql pdo_oci pdo_odbc pdo_pgsql pdo_sqlite pgsql phar posix pspell readline recode reflection session shmop simplexml snmp soap sockets sodium spl standard sysvmsg sysvsem sysvshm tidy tokenizer wddx xml xmlreader xmlrpc xmlwriter xsl zend_test zip

              注:大部分扩展在 docker-php-ext-install 安装之前,需要先用 yum or apt-get 安装所需要的系统依赖库,具体需要参考各扩展的文档。

3. 创建 docker-compose.yml

    $ cd /home/docker/laravel
    $ vim docker-compose.yml

version: "3"
        services:
            nginx:
                image: nginx
                container_name: nginx-php7.4
                ports:
                    - "80:80"
                restart: always
                volumes:
                    - /home/docker/nginx/conf.d:/etc/nginx/conf.d
                    - /home/docker/nginx/html:/usr/share/nginx/html
                    - /home/docker/nginx/logs:/var/log/nginx
            mariadb:
                image: mariadb:10.4
                container_name: mariadb-10.4
                ports:
                    - "3306:3306"
                restart: always
                environment:
                    - MARIADB_ROOT_PASSWORD=123456
                volumes:
                    - /home/docker/mysql/conf:/etc/mysql/conf.d
                    - /home/docker/mysql/data:/var/lib/mysql
                    - /home/docker/mysql/log:/var/log/mysql
            php:
                image: php:7.4-fpm-mysqli
                container_name: php-7.4-fpm-mysqli
                depends_on:
                    - nginx
                    - mariadb
                build: .
                ports:
                    - "9000:9000"
                restart: always
                volumes:
                    - /home/docker/php/conf.d:/usr/local/etc/php/conf.d
                    - /home/docker/nginx/html:/var/www/html

 

4. 配置文件

    1) 创建 nginx.conf

        在 /home/docker/nginx/conf.d 目录下,创建 nginx.conf 文件,内容如下:   

server {
                listen  80 default_server;
                server_name localhost;
                root   /usr/share/nginx/html;
            
                location / {
                    index index.php index.html index.htm;
                    autoindex off;
                }

                location ~ \.php(.*)$ {
                    root   /var/www/html;
                    
                    fastcgi_pass php-7.4-fpm-mysqli:9000;
                    fastcgi_index index.php;
                    fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
                    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                    fastcgi_param PATH_INFO $fastcgi_path_info;
                    fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
                    include  fastcgi_params;
                }
            }

            参数说明:

                (1) server.location.fastcgi_pass: php-7.4-fpm-mysqli:9000 表示 “容器名称:端口”,也可以写成 “ip:端口”,获取 ip 的方法,运行如下命令:
                
                    $ docker inspect --format='{{.NetworkSettings.IPAddress}}' php-7.4-fpm-mysqli

                        172.17.0.4

                (2) 目录映射关系:
                
                    server.root: /usr/share/nginx/html 是 nginx 容器内的路径。静态文件 (HTML/CSS/JS/Images 等文件)对应的映射目录是 usr/share/nginx/html;

                    server.location.root: /var/www/html/ 是 php 容器内的路径。 php 文件(*.php)通过 location ~ \.php(.*)$ 解析,对应的映射目录是 /var/www/html/。

                    把 nginx 容器内的路径 /usr/share/nginx/html 和 php 容器内的路径 /var/www/html/ 都挂载到 Docker 所在主机的目录 /home/docker/nginx/html,这个目录就同时支持 php 文件和静态文件的解析。

                (3) 使用虚拟域名,如 www.test.com,只需在 Docker 所在主机的 /etc/hosts 添加 127.0.0.1    www.test.com,不必在 nginx 容器或 php 容器中添加。
 
    2) 创建 my_mariadb.cnf 文件

        在 /home/docker/mysql/conf 目录下,创建 my_mariadb.cnf 文件,内容如下:

[mysqld]
            server-id=1
            port=3306
            
            #basedir=/usr/local/mysql
            #tmpdir=/tmp
            datadir=/var/lib/mysql

            # 查询日志,默认在 /var/lib/mysql 目录下
            #general_log=1
            #general_log_file=mysql_general.log

            # 二进制日志,默认在 /var/lib/mysql 目录下
            #log_bin=mysql_log_bin-1

            # 慢查询日志,默认在 /var/log/mysql 目录下
            #slow_query_log=1
            #long_query_time=1
            #slow_query_log_file=mysql_slow_query.log

            # 错误日志,指定到 /var/log/mysql 目录
            log_error=/var/log/mysql/mysql_err.log

  注:MariaDB (MySQL) 的默认配置文件是 /etc/mysql/my.cnf 文件。如果想要自定义配置,在 /etc/mysql/conf.d 目录中创建 *.cnf 文件。新建的文件可以任意起名,只要保证后缀名是 cnf 即可。新建的文件中的配置项可以覆盖 /etc/mysql/my.cnf 中的配置项。

    3) 创建 my_php.ini 文件

        在 /home/docker/php/conf.d 目录下,创建 my_php.ini 文件,内容如下:

file_uploads=On

	upload_max_filesize=10M
	post_max_size=10M
	memory_limit=20M

	extension=mysqli.so
        extension=pdo_mysql.so
        extension=sodium
        extension=zip.so

        注:PHP 的配置文件在容器内 /usr/local/etc/php/conf.d 目录。如果想要自定义配置,在该 目录中创建 *.ini 文件。新建的文件可以任意起名,只要保证后缀名是 ini 即可。新建的文件中的配置项可以覆盖原来的配置项。

              docker build 调用 docker-php-ext-install 命令安装 php 扩展时,会在 /usr/local/etc/php/conf.d 目录下创建扩展的配置文件,比如 docker-php-ext-pdo_mysql.ini,内容如下:

                    extension=pdo_mysql.so

               挂载目录 “- /home/docker/php/conf.d:/usr/local/etc/php/conf.d” 时, docker-php-ext-pdo_mysql.ini 等配置文件会丢失,所以需要把这些配置文件的内容加入到 my_php.ini 文件。docker build 安装的所有 php 扩展的配置,都需要添加到 my_php.ini 文件里,否者有些 php 扩展无法正常工作。

    4) 测试文件

        在 /home/docker/nginx/html 目录下,创建 test.html 文件,内容如下:

            <h3>Nginx/PHP7.4 - test.html</h3>

        在 /home/docker/nginx/html 目录下,创建 demo.php 文件,内容如下:

            <?php
                echo "Nginx/PHP7.4 - PHP file demo.php";
            ?>

5. 启动

    $ cd /home/docker/laravel   # 进入 docker-compose.yml 所在目录

    $ docker-compose up     # 执行 docker-compose.yml
    $ docker-compose up -d   # 在后台运行

[+] Running 4/4
        ⠿ Network laravel_default           Created            0.0s
        ⠿ Container mariadb-10.4            Started            0.5s
        ⠿ Container nginx-php7.4            Started            0.5s
        ⠿ Container php-7.4-fpm-mysqli      Started            0.8s

        注:本地 docker 没有所需要的镜像时,会自动下载所需的镜像。遇到无法自动下载的情况,可以使用 docker pull 命令下载所需的镜像,在运行 docker-compose up 命令。
        
    $ docker images     # 查看镜像

REPOSITORY   TAG              IMAGE ID       CREATED          SIZE
        php          7.4-fpm-mysqli   fbca0f9390a3   21 minutes ago   444MB
        php          7.4-fpm          cf71a2f33ec4   24 minutes ago   444MB
        nginx        latest           2d389e545974   5 days ago       142MB
        mariadb      10.4             801fdf0164b2   2 weeks ago      404MB

    $ docker ps             # 查看容器运行情况

CONTAINER ID   IMAGE               ...   PORTS                     NAMES
        c663e5fc3b3f   php:7.4-fpm-mysqli    0.0.0.0:9000->9000/tcp,...  php-7.4-fpm-mysqli
        397a6488239e   mariadb:10.4          0.0.0.0:3306->3306/tcp,...  mariadb-10.4
        7d4d9fa56ed6   nginx                 0.0.0.0:80->80/tcp,...      nginx-php7.4

    $ docker-compose ps     # 类似 docker ps 的作用

NAME                COMMAND    SERVICE    STATUS         PORTS
        mariadb-10.4        ...        mariadb    running    0.0.0.0:3306->3306/tcp,...
        nginx-php7.4                   nginx      running    0.0.0.0:80->80/tcp,...
        php-7.4-fpm-mysqli             php        running    0.0.0.0:9000->9000/tcp,...

 

    mariadb-10.4 容器内的程序要在 /home/docker/mysql/log (该目录被挂载到容器内 /var/log/mysql 目录) 目录下创建 log 文件,需要确保容器内 root/root 以外的用户也有 /home/docker/mysql/log 目录的写权限,修改该目录的权限,命令如下:

     $ cd /home/docker/mysql
  $ chmod a+w log

    修改后需要重启 mariadb-10.4 容器,命令如下:

     $ docker restart mariadb-10.4

 

    浏览器访问 http://192.168.0.10/test.html,静态页面显示如下:

        Nginx/PHP7.4 - test.html

    浏览器访问 http://192.168.0.10/demo.php,动态页面显示如下:

        Nginx/PHP7.4 - PHP file demo.php

6. 停止

    $ docker-compose stop   # 停止容器,类似 docker stop 的作用

[+] Running 3/3
        ⠿ Container php-7.4-fpm-mysqli  Stopped          0.1s
        ⠿ Container mariadb-10.4        Stopped          1.8s
        ⠿ Container nginx-php7.4        Stopped          0.2s

 

    $ docker-compose ps     # 查看容器,类似 docker ps -a 的作用

NAME                COMMAND     SERVICE     STATUS        PORTS
        mariadb-10.4        ...         mariadb     exited (0)
        nginx-php7.4                    nginx       exited (0)
        php-7.4-fpm-mysqli              php         exited (0)

    $ docker-compose down   # 停止并删除容

[+] Running 4/0
        ⠿ Container php-7.4-fpm-mysqli    Removed          0.1s
        ⠿ Container mariadb-10.4          Removed          1.9s
        ⠿ Container nginx-php7.4          Removed          0.1s
        ⠿ Network laravel_default         Removed          0.0s

        类似 docker stop 和 docker rm 的复合作用。

    $ docker-compose ps        

        NAME            COMMAND     SERVICE     STATUS        PORTS

       此时容器列表为空。

    $ docker images     # 查看镜像

REPOSITORY   TAG              IMAGE ID       CREATED          SIZE
        php          7.4-fpm-mysqli   fbca0f9390a3   33 minutes ago   444MB
        php          7.4-fpm          cf71a2f33ec4   36 minutes ago   444MB
        nginx        latest           2d389e545974   5 days ago       142MB
        mariadb      10.4             801fdf0164b2   2 weeks ago      404MB

        运行 docker-compose down 不会删除镜像,Docker 所在主机上挂载的目录里数据和文件也不会被删除,运行 docker-composer up 或  up -d 就可以恢复运行。

7. 配置 Laravel 项目

    1) 项目创建环境

        操作系统:Windows 10 Home 21H2
        PHP 版本:7.4.25,https://www.php.net/
        PHP Composer 版本:2.4.2,https://getcomposer.org/
        Nginx 版本:1.20.2,http://nginx.org/en/

    2) 创建 Laravel 项目

        运行 Composer 命令创建项目:

            C:\laravel>composer create-project laravel/laravel laravel-demo
                ...
            C:\laravel>tar -cvzf laravel-demo.tar.gz laravel-demo

        配置 Windows/Nginx 测试 laravel-demo 项目,修改 conf/nginx.conf 内容如下:

...
            
            http {

                ...

                server {
                    listen       8888;
                    server_name  localhost;

                    location / {
                        root   C:\laravel\laravel-demo\public;
                        index  index.php index.html index.htm;
                        
                       # 根据 laravel 规则进行 url 重写
                       try_files $uri $uri/ /index.php?$query_string;
                    }

                    location ~ \.php$ {
                        root           C:\laravel\laravel-demo\public;
                        fastcgi_pass   127.0.0.1:9000;
                        fastcgi_index  index.php;
                        #fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
                        
                        fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
                        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                        fastcgi_param PATH_INFO $fastcgi_path_info;
                        fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;

                        include        fastcgi_params;
                    }
                }

                ...
            }

 

   启动 fastcgi,运行如下命令:

            C:\laravel>php-cgi.exe -b 127.0.0.1:9000

        启动 nginx  (假设安装目录 C:\Applications\nginx-1.20.2),双击目录下的 nginx.exe 文件或在命令行下运行如下命令:

             C:\Applications\nginx-1.20.2>nginx

        浏览器访问 http://localhost:8888/,显示 Laravel 空项目的默认页面。 

 

        注:Laravel 项目创建过程,可以参考 https://laravel.com/docs/9.x/installation#your-first-laravel-project

 

    3) 部署 laravel-demo

        把 laravel-demo.tar.gz 上传到 192.168.0.10 主机的 /home/docker/laravel 目录。

        $ cd /home/docker/laravel
        $ tar -vxzf laravel-demo.tar.gz
        $ cd laravel-demo
        $ ls

            app      bootstrap      composer.lock  database      phpunit.xml  README.md  routes      storage  vendor
            artisan  composer.json  config         package.json  public       resources  server.php  tests    webpack.mix.js

    4) 修改 docker-compose.yml

        $ cd /home/docker/laravel
        $ vim docker-compose.yml

version: "3"
            services:
                nginx:
                    image: nginx
                    container_name: nginx-php7.4
                    ports:
                        - "80:80"
                    restart: always
                    volumes:
                        - /home/docker/nginx/conf.d:/etc/nginx/conf.d
                        - /home/docker/laravel/laravel-demo/public:/usr/share/nginx/html
                        - /home/docker/nginx/logs:/var/log/nginx
                mariadb:
                    image: mariadb:10.4
                    container_name: mariadb-10.4
                    ports:
                        - "3306:3306"
                    restart: always
                    environment:
                        - MARIADB_ROOT_PASSWORD=123456
                    volumes:
                        - /home/docker/mysql/conf:/etc/mysql/conf.d
                        - /home/docker/mysql/data:/var/lib/mysql
                        - /home/docker/mysql/log:/var/log/mysql          
                php:
                    image: php:7.4-fpm-mysqli
                    container_name: php-7.4-fpm-mysqli
                    depends_on:
                        - nginx
                        - mariadb
                    build: .
                    ports:
                        - "9000:9000"
                    restart: always
                    volumes:
                        - /home/docker/php/conf.d:/usr/local/etc/php/conf.d
                        - /home/docker/laravel/laravel-demo/public:/var/www/html
                        - /home/docker/laravel/laravel-demo:/var/www

        注:修改 services.nginx.volumes,挂载 /home/docker/laravel/laravel-demo/public:/usr/share/nginx/html。

            修改 services.php.volumes,挂载 /home/docker/laravel/laravel-demo/public:/var/www/html 和 /home/docker/laravel/laravel-demo:/var/www。
              
            laravel-demo 的入口文件是 laravel-demo/public/index.php,所以挂载 /home/docker/laravel/laravel-demo/public:/var/www/html 。

            挂载 /home/docker/laravel/laravel-demo:/var/www,是因为 laravel-demo/public/index.php 需要用到它上级目录里的文件,所以上级目录也需要挂载。

 

    5) 修改 nginx.conf

        $ cd /home/docker/nginx/conf.d

   $ vim nginx.conf

server {
                listen  80 default_server;
                server_name localhost;
            
                location / {
                    root   /usr/share/nginx/html;
                    index index.php index.html index.htm;

                    # 根据 laravel 规则进行 url 重写
                    try_files $uri $uri/ /index.php?$query_string;
                }

                location ~ \.php(.*)$ {
                    root   /var/www/html;
                    
                    fastcgi_pass php-7.4-fpm-mysqli:9000;
                    fastcgi_index index.php;
                    fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
                    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                    fastcgi_param PATH_INFO $fastcgi_path_info;
                    fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
                    include  fastcgi_params;
                }
            }

 

    6) 运行

        $ cd /home/docker/laravel
        $ docker-compose up -d

        浏览器访问 http://192.168.0.10/,显示 Laravel 空项目的默认页面。

8. 配置 phpMyAdmin

    1) 下载 phpMyAdmin
    
        phpMyAdmin 官网: https://www.phpmyadmin.net/,本文使用 phpMyAdmin 4.9.3。

        $ cd /home/docker/laravel
        $ wget https://files.phpmyadmin.net/phpMyAdmin/4.9.3/phpMyAdmin-4.9.3-all-languages.tar.gz
        $ tar -vxzf phpMyAdmin-4.9.3-all-languages.tar.gz
        $ mv phpMyAdmin-4.9.3-all-languages phpmyadmin

    2) 配置 MariaDB 连接

        $ cd /home/docker/laravel/phpmyadmin
        $ cp config.sample.inc.php config.inc.php
        $ vim config.inc.php            ... 

/**
            * First server
            */
            $i++;
            /* Authentication type */
            $cfg['Servers'][$i]['auth_type'] = 'config';
            /* Server parameters */
            //$cfg['Servers'][$i]['host'] = '192.168.0.10';
            $cfg['Servers'][$i]['host'] = 'mariadb-10.4';          
            $cfg['Servers'][$i]['user'] = 'root';
            $cfg['Servers'][$i]['password'] = '123456';
            $cfg['Servers'][$i]['compress'] = false;
            $cfg['Servers'][$i]['AllowNoPassword'] = false;

            ...

            /**
             * Directories for saving/loading files from server
             */
       $cfg['UploadDir'] = './storage/uploads/';
           $cfg['SaveDir'] = './storage/downloads';
           $cfg['TempDir'] = './storage/tmp';

           $cfg['ZipDump'] = true;

           ...

  注:这里的 storage 目录在 phpMyAdmin 的根目录下,把 storage 目录及其子目录的权限改成 777。

         ZipDump 开启支持导入/导出 zip 文件。

    auth_type 设置为 cookie 时,访问 phpMyAdmin 页面,需要输入用户名和密码。

3) 修改 docker-compose.yml

        $ cd /home/docker/laravel
        $ vim docker-compose.yml

version: "3"
            services:
                nginx:
                    image: nginx
                    container_name: nginx-php7.4
                    ports:
                        - "80:80"
                    restart: always
                    volumes:
                        - /home/docker/nginx/conf.d:/etc/nginx/conf.d
                        - /home/docker/laravel/laravel-demo/public:/usr/share/nginx/html
                        - /home/docker/nginx/logs:/var/log/nginx
                        - /home/docker/laravel/phpmyadmin:/usr/share/nginx/html/phpmyadmin
                mariadb:
                    image: mariadb:10.4
                    container_name: mariadb-10.4
                    ports:
                        - "3306:3306"
                    restart: always
                    environment:
                        - MARIADB_ROOT_PASSWORD=123456
                    volumes:
                        - /home/docker/mysql/conf:/etc/mysql/conf.d
                        - /home/docker/mysql/data:/var/lib/mysql
                        - /home/docker/mysql/log:/var/log/mysql          
                php:
                    image: php:7.4-fpm-mysqli
                    container_name: php-7.4-fpm-mysqli
                    depends_on:
                        - nginx
                        - mariadb
                    build: .
                    ports:
                        - "9000:9000"
                    restart: always
                    volumes:
                        - /home/docker/php/conf.d:/usr/local/etc/php/conf.d
                        - /home/docker/laravel/laravel-demo/public:/var/www/html
                        - /home/docker/laravel/laravel-demo:/var/www
                        - /home/docker/laravel/phpmyadmin:/var/www/html/phpmyadmin

            注:修改 services.nginx.volumes,挂载 /home/docker/laravel/phpmyadmin:/usr/share/nginx/html/phpmyadmin。
            
                修改 services.php.volumes,挂载 /home/docker/laravel/phpmyadmin:/var/www/html/phpmyadmin。
                
                也可以不挂载 phpmyadmin 目录,把整个目录复制到 /home/docker/laravel/laravel-demo/public 目录下,可以运行。为了保持项目的独立性,不建议复制整个 phpmyadmin 到 /home/docker/laravel/laravel-demo/public 目录下。

                另外,在 /home/docker/laravel/laravel-demo/public 目录下建立软链接到 phpmyadmin 也不可行,因为容器内无法读取软连接下的文件资源。   

    4) 运行

        $ cd /home/docker/laravel

        $ docker-compose down

        $ docker-compose up -d

        浏览器访问 http://192.168.0.10/phpmyadmin,页面显示 phpMyAdmin 主页。