Docker基础知识 (23) - 使用 Docker 部署 Nginx + Php/Laravel + MariaDB 项目 (2) | 配置 phpMyAdmin 目录密码保护


本文在 “Docker基础知识 (12) - 使用 Docker 部署 Nginx + Php/Laravel + MariaDB 项目” 基础上,修改 Nginx 的配置文件和 docker-compose.yml,配置 phpMyAdmin 目录密码保护。

注:本文省略了 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
    Build 目录:/home/docker/build
    HTML 目录:/home/docker/html


2. 创建 Dockerfile

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

        $ cd /home/docker/build
        $ 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

            # Install pdo_mysql mysqli zip
            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

            # Install gd
            RUN apt-get install -y libgd3 libgd-dev && rm -rf /var/lib/apt/lists/*
            RUN docker-php-ext-configure gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/
            RUN docker-php-ext-install -j$(nproc) gd

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

        gd 扩展的安装相对复杂一些,需要配置 freetype 等目录。

        $ 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   480MB
            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. 创建配置文件

    1) 创建 nginx.conf

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

            server {
                listen 80 default_server;
                server_name localhost;

                location / {
                    root /usr/share/nginx/html;
                    index index.html index.htm index.php;

                    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;
                    }
                }
            }

 

        本文使用的 Nginx 版本是 1.21.5,支持 fastcgi_cache 功能,如需缓存 PHP 页面 (以 WordPress 为例),可以配置 nginx.conf 内容如下:

            fastcgi_cache_path /var/cache/nginx/fcache levels=1:2 keys_zone=fcache_wordpress:10m inactive=10m max_size=1g;
            fastcgi_cache_key $request_method://$host$request_uri;
            fastcgi_cache_use_stale error timeout invalid_header http_500;
            fastcgi_ignore_headers Cache-Control Expires Set-Cookie;

            server {
                listen 80 default_server;
                server_name localhost;

                location / {
                    root /usr/share/nginx/html;
                    index index.html index.htm index.php;

                    set $skip_cache 0;
                    # POST 访问不缓存
                    if ($request_method = POST) {
                        set $skip_cache 1;
                    }

                    # 动态查询不缓存
                    if ($query_string != "") {
                        set $skip_cache 1;
                    }

                    # 后台等特定页面不缓存
                    if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
                        set $skip_cache 1;
                    }

                    # 登录用户、评论过的用户不展示缓存
                    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
                       set $skip_cache 1;
                    }

                    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;

                        # Cache 规则
                        fastcgi_cache fcache_wordpress;      # 使用 keys_zone 的空间名字
                        fastcgi_cache_min_uses 1;            # 最小多少次访问相同 URL 将被缓存
                        fastcgi_cache_valid 200 10m;         # 缓存 10 分钟
                        fastcgi_cache_valid 302 3m;
                        fastcgi_cache_valid any 1m;

                        fastcgi_cache_bypass $skip_cache;
                        fastcgi_no_cache $skip_cache;
                        add_header X-Cache "$upstream_cache_status from $host";

                        include  fastcgi_params;
                    }
                }
            }

            参数说明:

                fastcgi_cache_path /var/cache/nginx/fcache 表示 Cache 存放路径,其它参数:

                    levels=1:2 表示设置 Cache 目录的目录分级以及子目录的数量,采用二级目录 Hash,最多 16:256
                    keys_zone=fcache_html:10m 表示设置内存空间 10 MB 用于保存关键字(key)及数据相关信息,官方文档提示 1 MB 能够容纳 8000 个 cache key;
                    inactive=10m 表示内存中的数据存储时间,默认为 10 分钟;
                    max_size=1g 表示最大硬盘占用空间为 1g;

                fastcgi_cache_key 表示 Cache 的关键字,一般用 URL 作为关键字;
                fastcgi_cache_use_stale 表示哪些情况下用过期缓存;
                fastcgi_ignore_headers 表示忽略 nocache 申明,避免不缓存伪静态等;


    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
        extension=gd.so

     # 关闭页面上的错误显示
display_errors=Off
error_reporting=E_ALL12

        注: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. 配置运行

    1) 创建 docker-compose.yml

        $ cd /home/docker/build
        $ 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/fcache:/var/cache/nginx/fcache - /home/docker/nginx/logs:/var/log/nginx - /home/docker/html/main:/usr/share/nginx/html 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/html/main:/var/www/html


    2) 创建测试文件

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

            <h3>HTML/MAIN - index.html</h3>

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

            <h3>HTML/MAIN - test.html</h3>

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

            <?php
                echo "HTML/MAIN - demo.php";
            ?>

    3) 运行

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

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

            [+] Running 4/4
            ⠿ Network build_default         Created         0.1s
            ⠿ Container mariadb-10.4        Started         0.7s
            ⠿ Container nginx-php7.4        Started         0.7s
            ⠿ Container php-7.4-fpm-mysqli  Started         1.1s


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

        $ 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

        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,静态页面显示如下:

            HTML/MAIN - index.html

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

            HTML/MAIN - test.html

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

            HTML/MAIN - demo.php


5. 配置 phpMyAdmin

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

        $ cd /home/docker/www
        $ 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/www/phpmyadmin
        $ cp config.sample.inc.php config.inc.php
        $ vim config.inc.php

            ...

            /**
            * First server
            */
            $i++;
            /* Authentication type */
            $cfg['Servers'][$i]['auth_type'] = 'cookie';
            /* Server parameters */
            //$cfg['Servers'][$i]['host'] = '192.168.0.10';
            $cfg['Servers'][$i]['host'] = 'mariadb-10.4';          
            $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 文件。

    3) 修改 docker-compose.yml

        $ cd /home/docker/build
        $ 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/fcache:/var/cache/nginx/fcache - /home/docker/nginx/logs:/var/log/nginx - /home/docker/html/main:/usr/share/nginx/html - /home/docker/html/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/html/main:/var/www/html - /home/docker/html/phpmyadmin:/var/www/html/phpmyadmin              


    4) 运行

        $ cd /home/docker/build

        $ docker-compose down
        $ docker-compose up -d

        浏览器访问 http://192.168.0.10/phpmyadmin,页面显示 phpMyAdmin 登陆页面,输入用户名 root 和密码 123456 登陆。

 

    5) 解决 PhpMyAdmin 4.x 加载速度缓慢

        国内或内网中 PhpMyAdmin 4.x 加载速度缓慢,通常因为无法访问 PhpMyAdmin 官网,而 PhpMyAdmin 页面会自动检查官网上的程序版本更新,一直在尝试连接官网。

        简单的解法方法是让 PhpMyAdmin 不检查更新,修改 PhpMyAdmin 目录下 version_check.php 文件,这里以 4.9.3 版本为例,内容修改如下:

            <?php
                /* vim: set expandtab sw=4 ts=4 sts=4: */
                /**
                * A caching proxy for retrieving version information from https://www.phpmyadmin.net/
                *
                * @package PhpMyAdmin
                */

                use PhpMyAdmin\Core;
                use PhpMyAdmin\VersionInformation;
                use PhpMyAdmin\Response;

                $_GET['ajax_request'] = 'true';

                require_once 'libraries/common.inc.php';

                // Disabling standard response.
                Response::getInstance()->disable();

                // Always send the correct headers
                Core::headerJSON();

                $versionInformation = new VersionInformation();
                //$versionDetails = $versionInformation->getLatestVersion();

                if (empty($versionDetails)) {
                    echo json_encode(array());
                } else {

                ...


        注:注释掉第 24 行检查更新的代码:

            //$versionDetails = $versionInformation->getLatestVersion();


6. 配置 phpMyAdmin 目录密码保护

   生产环境下访问 phpMyAdmin,auth_type 设置为 cookie 来保证安全,显得有点单薄。出于安全考虑,一般会设置 nginx 目录密码保护。

    1) 设置 nginx 目录密码保护

        在 /home/docker/nginx/conf.d 目录下,修改 nginx.conf 文件,添加内容如下:

            server {
                
                ...

                location ~ ^/phpmyadmin/.* {
                    root /usr/share/nginx/html;
                    index index.html index.htm index.php;

                    auth_basic "Enter username and password";
                    auth_basic_user_file /etc/nginx/conf.d/htpasswd;

                    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;
                }

            }


            注:auth_basic 配置简单认证功能,浏览器会提示用户输入用户名和密码,用户名和密码保存在 auth_basic_user_file 指定的文件里。

                这里 location ~ ^/phpmyadmin/.*,保护 phpmyadmin 目录下的所有文件。如果你只设了/phpmyadmin/ 那么 /phpmyadmin/index.php 不处于保护状态。 ^/phpmyadmin/.* 意为保护该目录下所有文件,只需要一次认证。

                auth_basic 配置在 location ~ ^/phpmyadmin/.* 内,所以认证范围就到 phpmyadmin 目录这一级。如果要整个 80 端口服务都处于认证状态,只需把 auth_basic 配置到 server {} 之下。

    2) 生成密码文件

        运行如下命令创建密码:

            $ openssl passwd -apr1

            Password:
            Verifying - Password:

            $apr1$kB6nvL23$bjdqD9Evw.QKxbVicInUj0


            注:命令 openssl passwd 提示用户输入两次密码,这里输入 654321,产生了一个 Apache MD5 密码 $apr1$kB6nvL23$bjdqD9Evw.QKxbVicInUj0 ,然后和用户名一起,以 [用户名]:[hash 密码] 的格式写入文本文件即可,这里设置用户名为 test。

                不同密码格式的参数如下:

                    (1) -crypt 表示生成标准的 UNIX 密码,是默认选项;
                    (2) -apr1 表示生成 Apache MD5 密码;
                    (3) -1 表示生成 BSD MD5 密码;

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

            test:$apr1$kB6nvL23$bjdqD9Evw.QKxbVicInUj0

    3) 运行

        $ cd /home/docker/build

        $ docker-compose down
        $ docker-compose up -d

        浏览器访问 http://192.168.0.10/phpmyadmin,弹出验证对话框,输入 test / 654321,页面显示 phpMyAdmin 主页。
        
        如果 auth_type 设置为 cookie 时,访问 phpMyAdmin 页面,需要输入数据库账号 root / 123456 。


posted @ 2023-01-10 12:40  垄山小站  阅读(529)  评论(0)    收藏  举报