Hyperf 3.1 在 Docker 中实现 MySQL 协程连接需满足三要素:PHP ≥ 8.1 且启用 Swoole ≥ 5.0 协程支持、Dockerfile 中显式调用 SwooleRuntime::enableCoroutine(true)、databases.php 正确配置 pool 及 driver => 'mysql',并确保 Docker 网络与环境变量对齐。

Hyperf 3.1 在 Docker 中部署时,MySQL 协程连接不是靠“Docker 配置”实现的,而是靠容器内 PHP 环境、Swoole 扩展和 Hyperf 的配置三者协同生效。Docker 只是运行环境载体,关键在镜像构建和配置文件是否满足协程 MySQL 的硬性要求。
确保基础运行环境合规
你的 Docker 镜像必须满足以下三点,缺一不可:
- PHP 版本 ≥ 8.1(推荐 8.3)
- 已启用 Swoole 扩展,且版本 ≥ 5.0.0,并确认支持协程:
php --ri swoole 输出中必须含 support coroutines: enabled - 已安装 hyperf/db-connection 和 hyperf/database 包(通常通过 composer install 自动完成)
Dockerfile 中需显式启用 Swoole 协程运行时
仅装扩展不够,还需在启动前启用协程支持。在 Dockerfile 的 CMD 或 entrypoint 脚本中加入:
php -r "SwooleRuntime::enableCoroutine(true);" -f bin/hyperf.php start
或更稳妥地,在 bin/start.sh 中写:
#!/bin/sh php -r "SwooleRuntime::enableCoroutine(true);" -f bin/hyperf.php start
然后在 Dockerfile 中用 CMD ["sh", "bin/start.sh"] 启动。
正确配置 databases.php 连接池(核心步骤)
打开 config/autoload/databases.php,MySQL 配置块中必须包含 pool 子数组,且 driver 必须为 'mysql'(非 pdo_mysql):
'mysql' => [
'driver' => env('DB_DRIVER', 'mysql'),
'host' => env('DB_HOST', 'mysql'),
'port' => (int) env('DB_PORT', 3306),
'database' => env('DB_DATABASE', 'hyperf'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'charset' => env('DB_CHARSET', 'utf8mb4'),
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
'prefix' => env('DB_PREFIX', ''),
'strict' => true,
'pool' => [
'min_connections' => 2,
'max_connections' => 20,
'connect_timeout' => 5.0,
'wait_timeout' => 3.0,
'heartbeat' => -1,
'max_idle_time' => 60.0,
],
],
注意:
• DB_HOST 不要写 localhost,应填 Docker 网络中 MySQL 服务名(如 mysql)
• .env 中 DB_DRIVER 必须是 mysql,不能是 pdo_mysql 或 mysqli
• 若用 Swow 引擎,则需改用 Swow 专用 pool 参数并删掉旧 pool 结构
docker-compose.yml 网络与环境对齐
确保 Hyperf 容器能访问 MySQL 容器,且环境变量传递正确:
services:
app:
build: .
environment:
- DB_DRIVER=mysql
- DB_HOST=mysql
- DB_PORT=3306
- DB_DATABASE=hyperf
- DB_USERNAME=root
- DB_PASSWORD=123456
depends_on:
- mysql
networks:
- hyperf-net
<p>mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: hyperf
ports:</p>
- "3306:3306" networks:
- hyperf-net
networks 必须统一,避免因默认 bridge 网络导致 DNS 解析失败。
验证协程连接是否真正生效
部署后,进容器执行一次并发查询测试:
php -r "
$container = require_once __DIR__.'/runtime/container.php';
$conn = $container->get(HyperfDatabaseConnection::class);
go(function() use ($conn) {
$start = microtime(true);
$conn->select('SELECT SLEEP(1)');
$conn->select('SELECT SLEEP(1)');
echo '总耗时: ' . round(microtime(true) - $start, 2) . "s\n";
});"
若输出约 1.0x 秒(而非 2.x 秒),说明协程连接池已正常工作。











