Laradock 与 MySQL 8.0 历险记

Laradock 是什么?

Laradock 是一个 PHP 的 docker 集成环境,支持多种 PHP、DB及常用工具版本,能够快速搭建开发生产环境。

Laradock 配置说明

容器操作

启动容器

在 laradock 根目录设置好.env文件后,执行命令docker-compose up -d nginx mysql redis workspace启动所需容器

docker-compose 命令会依赖docker-compose.yml文件。

停止容器

在 laradock 根目录执行docker-compose stop
在任意目录执行docker stop $(docker ps -q)会停止所有正在运行中的容器

停止并删除容器

在 laradock 根目录执行docker-compose down

谨慎使用该命令 !!!

进入容器

laradock 目录下 执行docker-compose exec [container] bash命令,如:

1
2
3
$ docker-compose exec workspace bash      // 进入工作区
$ docker-compose exec mysql bash // 进入 MySQL
$ docker-compose exec redis bash // 进入 Redis

构建容器

1
2
$ docker-compose build workspace
$ docker-compose build mysql

Nginx 站点配置

位于 laradock 根目录下的../nginx/sites/*.conf

为什么选择 MySQL 8?

MySQL 8.0 于 2016 年 9 月发布,在 2018 年 4 月发布第一个通用可用版本。目前为止,MySQL8 的使用还处于小范围的尝鲜阶段,经过近两年的正式版,我任务很多人已经趟过不少坑了,加之升级是未来的趋势,不如早日适应。

在 MySQL 8 中,主要有以下的一些优化:

  • 字符集默认支持 uft8mb4,很好的支持了 emoji,再也不是 latin1 了
  • 新能较 5.7 提升了两倍
  • JSON 的优化支持
  • 连接方式由 mysql_native_password 修改为 caching_sha2_password

Laravel 配置说明

Laravel 连接 Laradock 数据库

.env文件需配置为DB_HOST=mysql,不能是127.0.0.1localhost。如果需使用数据库软件连接,需修改为host 可为127.0.0.1localhost

这是因为127.0.0.1localhost表示本机回环地址,php 代码是运行在 php 容器中的,与 MySQL 容器相隔离,因此需要设为mysql。MySQL 容器与数据库软件运行于同一宿主机环境,因此可用127.0.0.1localhost

MySQL 8 的认证变化

MySQL 8.0 将密码验证方式由以前的 mysql_native_password 改为了 caching_sha2_password,以获得更快的连接速度,但目前caching_sha2_password的支持尚不完善,因此连接时可能会出现认证错误。

PHP 7.4 版本已经支持了 caching_sha2_password,因此可以直接连接,该版本以下则需要使用命令ALTER USER 'YOURUSERNAME'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YOURPASSWORD';修改账户的连接方式。修改前可使用命令SELECT user,host,plugin from mysql.user where user='root';查询当前连接方式。

另外,当前大多数据库GUI客户端尚不支持 caching_sha2_password 方式,因此需要将 DB 软件的连接账号设置为传统的 mysql_native_password。或者使用终端连接数据库查询,终端查询推荐 mycli 工具,以下是使用示例

由于代码运行于 Laradock 的 workspace 容器,因此当我们在宿主机执行涉及数据库的终端命令时,会出现矛盾的情况:

  1. 代码以DB_HOST=mysql连接数据库,宿主机则以127.0.0.1连接,因此 dsn 错误而无法连接,需要临时修改DB_HOST,但这样容易忘记改回去,不建议操作
  2. 执行中一些依赖目录的代码在宿主机可能会无法正常运行
    综上,容器中执行终端脚本时需要在容器中执行,请勿在宿主机中执行。

参考资料

  1. PHP 7.4 修复 MySQL 8 连接问题
  2. MySQL 8 连接变更的官方说明

连接 Redis

Laravel Redis 依赖 predis 或者 phpredis,前者纯 php 编写,composer 快捷安装,但作者已经弃坑,未来Laravel 会移除对其支持,采用 socket 连接到 Redis(每次请求均需连接 Redis),后者则是使用 C 语言编写的扩展,可以保持对 Redis 的长连接(pconnect),具备更好的性能,因此若业务对 Redis 依赖性较强,推荐使用 phpredis。

Laravel 中的 Redis 注意事项

Laravel 的config/database.php中默认使用phpredis,若使用predis,则注意需要修改REDIS_CLIENT

Laravel 中统一使用Illuminate\Support\Facades\Redis中的命令,屏蔽了 predis 与 phpredis 命令的差异,建议使用。

predis 直接连接

predis 的new Predis\Client();是使用tcp://127.0.0.1:6379默认连接,而非读取 Laravel 的Redis配置,默认配置信息位于src/Connection/Parameters.php中的

1
2
3
4
5
private static $defaults = array(
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,
);

如果连接非本机 Redis,可使用new Predis\Client('tcp://10.0.0.1:6379');连接。

常见错误

宿主机执行与数据库相关命令时遇到以下错误:

1
Illuminate\Database\QueryException  : SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: nodename nor servname provided, or not known  

这是由于宿主机无法正确连接容器中的数据库,请前往容器中执行

数据库连接报错

使用以下代码直接连接数据库验证是否 DB 配置错误,然后根据错误提示借助搜索引擎逐步排查错误

1
$db_test = mysqli_connect('host', 'username', 'password');
因为热爱,所以执着。