Linxu 下搭建 Nginx、PHP 和 MariaDB 称之为 LNMP,那么我们在 Docker 下搭建就叫 DNMP 吧(虽然我不知道这样叫是否正确)。

配置单机网桥

由于这几个镜像相互之间需要通信,最好的解决方案是创建一个容器网络。
因此我们首先需要创建 Docker 网络 localnet,用于 docker 之间的通信。

1
2
3
4
5
# Linux
$ docker network create -d bridge localnet

# Windows
> docker network create -d nat localnet

查看创建好的网络。

1
2
3
4
5
6
7
8
$ docker network list
NETWORK ID NAME DRIVER SCOPE
b7228b827811 bridge bridge local
af39f057ff30 host host local

363014e0c45c localnet bridge local

007b2a216146 none null local

NAME 为 localnet 的网络即为新建的网络,后续创建的 Docker 容器就将加入该网络中。

安装 php7

下载 php7 镜像

php 有很多版本,我们可以在 官方仓库 搜索自己需要的镜像。
找到需要的镜像后,首先下载镜像:

1
$ docker pull php:7.4.4-fpm

这里以 php:7.4.4-fpm 为例。

镜像是否下载成功,可以通过以下指令确认。

1
2
3
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
php 7.4.4-fpm 7d64b9cd1388 2 days ago 405MB

安装 php7 镜像到容器

现在可以将镜像运行到容器中。

1
docker run -d --name php7 --network localnet -v /home/<your-username>/docker/nginx/www/html:/var/www/html --restart=always php:7.4.4-fpm

参数说明:

  • <your-username> 表示系统用户名 我习惯将 docker 相关文件放在默认用户名下面便于备份(下同)
  • -d 后台方式运行
  • –name php7 容器名称
  • –network localnet 加入到网络 localnet 中
  • –restart=always 系统重启后自动运行
  • –privileged=true 应用容器获取宿主机 root 权限
  • -v /home/<your-username>/docker/nginx/www/html:/var/www/html 将 nginx 的网站根目录(宿主机目录)映射到 php7 容器的网站根目录
  • -v /home/<your-username>/docker/php/www.conf:/usr/local/etc/php-fpm.d/www.conf php 的配置文件映射(可选)
  • -v /home/<your-username>/docker/php/log:/var/log 日志目录映射(可选)
    php7 需要使用 9000 端口提供给 nginx 使用,由于使用了 docker 容器网络 localnet 在容器之间通信,因此这里就不需要再将 9000 端口映射到宿主机。

容器运行成功,可以执行以下指令查看运行情况:

1
2
3
4
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

10d9826eef99 php:7.4.4-fpm "docker-php-entrypoi…" 4 seconds ago Up 4 seconds 9000/tcp php7

安装 mysqli 扩展

php 默认不安装 mysqli 扩展,我们需要手动安装。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 进入容器
$ docker exec -ti <your-php-container> /bin/bash

# 安装 mysqli 扩展

>> docker-php-ext-install mysqli

# 安装 pdo 和 pdo_mysql (可选)

>> docker-php-ext-install pdo pdo_mysql

# 国外网站找到的参考资料,还需要做以下两步,实测不需要。这里做个记录备忘。

# 执行第一步会提示:warning: mysqli (mysqli.so) is already loaded!

# 执行第二步会提示:bash: apachectl: command not found

>> docker-php-ext-enable mysqli

>> apachectl restart

<your-php-container> 表示容器名称。

安装成功后,退出容器,然后重启容器即可。

1
2
3
4
5
# 退出容器
$ exit

# 重启容器
$ docker restart <your-php-container>

有的扩展不用重启,自己试试即可。

安装 nginx

下载 nginx 镜像

nginx 可以使用以下指令直接下载镜像,默认下载最新版。

1
$ docker pull nginx

下载完成后,检查一下下载镜像。

1
2
3
4
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
php 7.4.4-fpm 7d64b9cd1388 2 days ago 405MB
nginx latest 6678c7c2e56c 2 weeks ago 127MB

安装 nginx 镜像到容器

执行以下指令将镜像运行到容器中。

1
docker run -d --name nginx --network localnet -p 80:80 -p 443:443 -v /home/<your-username>/docker/nginx/etc/nginx:/etc/nginx -v /home/<your-username>/docker/nginx/www/html:/usr/share/nginx/html -v /home/<your-username>/docker/nginx/logs:/var/log/nginx --restart=always nginx

参数说明

  • -d 后台执行
  • –name nginx 容器名称
  • –network localnet 加入到网络 localnet 中
  • –restart=always 系统重启后自动运行
  • –privileged=true 应用容器获取宿主机 root 权限
  • -p 80:80 映射 80 端口到宿主机
  • -p 443:443 映射 443 端口到宿主机
  • -v /home/<your-username>/docker/nginx/etc/nginx:/etc/nginx 映射 nginx 配置文件夹
  • -v /home/<your-username>/docker/nginx/www/html:/usr/share/nginx/html 映射 nginx 网站根路径
  • -v /home/<your-username>/docker/nginx/logs:/var/log/nginx 映射日志文件夹

配置 nginx 支持 php

从容器中复制默认配置文件

如果没有 nginx 的配置文件,可以暂不映射配置文件夹,先把容器临时跑起后,从容器中将配置文件复制出来后,再删除容器重新安装。

1
2
 # 从容器中复制文件, nginx 是容器名称,“:”号后面是要复制的路径,最后是要目的路径。
$ docker cp nginx:/etc/nginx ./

修改 php 配置

修改宿主机中的 nginx 配置文件,本文地址是:/home/<your-username>/docker/nginx/etc/nginx
在配置文件中增加或者修改 php 解析配置如下:

1
2
3
4
5
6
7
  location ~ \.php$ {

try_files $uri = 404;
fastcgi_pass php7:9000;
fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
include fastcgi_params;
}

注意两个参数:

  • php7 这是 php 容器的名字,nginx 通过该名字访问 php 容器。
  • /var/www/html/ 这是 php 容器中的网站根路径(不是宿主机路径)

测试 nginx

查看容器运行

容器运行成功,执行以下指令查看运行情况:

1
2
3
4
5
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fa527e2f7b17 nginx "nginx -g 'daemon of…" 6 seconds ago Up 5 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp nginx

10d9826eef99 php:7.4.4-fpm "docker-php-entrypoi…" 3 hours ago Up 33 minutes 9000/tcp php7

测试 www 服务

现在你可以输入 宿主机的 ip 地址 来测试你的网站。
在此之前别忘了在网站根目录放入测试网页:index.html。

测试 php 服务

在网站根目录新建 php 测试文件:phpinfo.php,并输入以下内容:

1
2
3
4
<?
phpinfo();

?>

在浏览器输入该文件地址进行测试,正常会显示 PHP 相关信息。

设置网站根目录所有权权限

现在 nginx 已经正常运行,但是遇见网站程序要写入硬盘的时候,系统会提示文件夹没有写入权限。
那么,我们需要到容器中设置网站根目录的所有权(当然,你也可以设置到需要写入权限的文件夹上)。

1
2
3
4
5
6
7
8
# 进入容器
$ docker exec -it nginx /bin/bash

# 进入 nginx 目录
$ cd /usr/share/nginx

# 设置网站根目录所有权为 www-data
$ chown -R www-data:www-data ./

docker 中运行的 nginx 和 php 都是以 www-data 身份运行的。

安装 mariadb

下载 mariadb 镜像

mariadb 也可以使用以下指令直接下载镜像,默认下载最新版。

1
$ docker pull mariadb

下载完成后,检查一下下载镜像。

1
2
3
4
5
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mariadb latest 37f5f0a258bf 41 hours ago 356MB
php 7.4.4-fpm 7d64b9cd1388 2 days ago 405MB
nginx latest 6678c7c2e56c 2 weeks ago 127MB

安装 mariadb 镜像到容器

执行以下指令将镜像运行到容器中。

1
docker run -d --name mariadb  --network localnet -e MYSQL_ROOT_PASSWORD=rootpassword -e MYSQL_USER=username -e MYSQL_PASSWORD=userpassword -v /home/<your-username>/docker/mariadb/data:/var/lib/mysql --restart=always mariadb --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

参数说明

  • -d 后台执行
  • –name mariadb 容器名称(注意:php 程序配置数据库地址,请填入该名称)
  • –network localnet 加入到网络 localnet 中
  • –restart=always 系统重启后自动运行
  • –privileged=true 应用容器获取宿主机 root 权限
  • -p 3306:3306 映射 3360 端口到宿主机(如不提供外网访问,可不映射)
  • -e MYSQL_ROOT_PASSWORD=rootpassword root 密码
  • -e MYSQL_USER=username 创建普通用户名
  • -e MYSQL_PASSWORD=userpassword 创建用户的密码
  • -v /home/<your-username>/docker/mariadb/data:/var/lib/mysql 库文件保存路径映射
  • –character-set-server=utf8mb4 字符集(一定要放在参数的末尾)
  • –collation-server=utf8mb4_unicode_ci 字符集(一定要放在参数的末尾)

成功运行,查看容器运行情况。

1
2
3
4
5
6
7
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

6df4e2434b29 mariadb "docker-entrypoint.s…" 6 seconds ago Up 5 seconds 3306/tcp mariadb
fa527e2f7b17 nginx "nginx -g 'daemon of…" 46 minutes ago Up 46 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp nginx

10d9826eef99 php:7.4.4-fpm "docker-php-entrypoi…" 4 hours ago Up About an hour 9000/tcp php7

安装 phpMyAdmin

下载和安装 phpMyAdmin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 进入 nginx 根目录
cd /home/<your-username>/docker/nginx/www/html

# 下载 phpMyAdmin 压缩文件
wget https://www.phpmyadmin.net/downloads/phpMyAdmin-latest-all-languages.tar.gz -O phpMyAdmin.tar.gz

# 解压缩
tar xzvf phpMyAdmin.tar.gz

# 重命名文件夹,源文件夹名称请根据实际情况修改
mv phpMyAdmin-4.8.5-all-languages phpMyAdmin

# 删除压缩文件
rm phpMyAdmin.tar.gz

配置 phpMyAdmin

1
2
3
4
5
6
7
8
# 进入 phpMyAdmin 目录
cd phpMyAdmin

# 创建 phpMyAdmin 配置文件
cp config.sample.inc.php config.inc.php

# 编辑配置文件
vim config.inc.php

修改以下配置信息:

设置 32 位长度的加密密码。

1
$cfg['blowfish_secret'] = 'abcdefghijklmnopqrstuvwxyz123456';

点击 这里 生成 32 位长度密码。

设置服务器名称:

1
$cfg['Servers'][$i]['host'] = 'databasename';

数据名称是 MariaDB 的容器名称,本示例中是 mariadb

开启高级功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$cfg['Servers'][$i]['pmadb'] = 'phpmyadmin';
$cfg['Servers'][$i]['bookmarktable'] = 'pma__bookmark';
$cfg['Servers'][$i]['relation'] = 'pma__relation';
$cfg['Servers'][$i]['table_info'] = 'pma__table_info';
$cfg['Servers'][$i]['table_coords'] = 'pma__table_coords';
$cfg['Servers'][$i]['pdf_pages'] = 'pma__pdf_pages';
$cfg['Servers'][$i]['column_info'] = 'pma__column_info';
$cfg['Servers'][$i]['history'] = 'pma__history';
$cfg['Servers'][$i]['table_uiprefs'] = 'pma__table_uiprefs';
$cfg['Servers'][$i]['tracking'] = 'pma__tracking';
$cfg['Servers'][$i]['userconfig'] = 'pma__userconfig';
$cfg['Servers'][$i]['recent'] = 'pma__recent';
$cfg['Servers'][$i]['favorite'] = 'pma__favorite';
$cfg['Servers'][$i]['users'] = 'pma__users';
$cfg['Servers'][$i]['usergroups'] = 'pma__usergroups';
$cfg['Servers'][$i]['navigationhiding'] = 'pma__navigationhiding';
$cfg['Servers'][$i]['savedsearches'] = 'pma__savedsearches';
$cfg['Servers'][$i]['central_columns'] = 'pma__central_columns';
$cfg['Servers'][$i]['designer_settings'] = 'pma__designer_settings';
$cfg['Servers'][$i]['export_templates'] = 'pma__export_templates';

将前面的注释代码去掉即可。

配置 $cfg[‘TempDir’] 权限

phpMyAdmin 为了提高性能需要写入临时文件,配置临时目录如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 进入容器
$ docker exec -it nginx /bin/bash

# 进入 nginx 目录
$ cd /usr/share/nginx/www/phpMyAdmin

# 新建文件夹 tmp
mkdir tmp

# 设置文件夹所有权
chown -R www-data:www-data tmp

# 设置文件夹读写权限
chmod -R 700 tmp

文件夹的所有权如果再 nginx 配置阶段已经设置,这里可忽略。
只需要检查写入权限即可。

登录 phpMyAdmin

现在你可以输入 phpMyAdmin 的地址访问你的数据库了。

首次登录系统会提示一个错误信息:
phpMyAdmin 高级功能尚未完全设置,部分功能未激活。查找原因。

点击后面的查找原因,按提示创建数据库 phpMyAdmin 即可。