本文在 “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 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 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; } } }
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 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. 配置运行
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/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/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 登陆。
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 。