PHP 8.5.5 连 Docker MySQL 的关键是容器网络通信、环境变量注入与服务名连接:必须用 docker-compose 中定义的 MySQL 服务名(如 db)代替 localhost 或 127.0.0.1,通过 environment 注入 DB_HOST 等变量,配合 MySQL 健康检查确保服务就绪后再连接,并在 DSN 中显式指定 charset=utf8mb4。

PHP 8.5.5 连 Docker 中的 MySQL,关键不是改 PHP 代码,而是让容器网络通、环境变量对、连接参数准——硬编码 localhost 或 127.0.0.1 必然失败。
为什么用服务名代替 localhost
Docker Compose 启动的 PHP 和 MySQL 容器默认在同一个自定义网络里,彼此通过服务名通信。PHP 容器里的 localhost 指的是它自己,不是 MySQL 容器。
- 若
docker-compose.yml中 MySQL 服务名为db,PDO 的 DSN 必须写成:mysql:host=db;port=3306;dbname=test - 写成
host=localhost或host=127.0.0.1会直接报Connection refused - 服务名必须和
docker-compose.yml里services:下一级的名称完全一致(区分大小写)
环境变量怎么安全传参
把数据库地址、密码写死在 PHP 文件里,既不安全也不利于多环境切换。应该靠 Docker 注入环境变量。
- 在
docker-compose.yml的 PHP 服务下加environment块:environment: - DB_HOST=db - DB_PORT=3306 - DB_NAME=test - DB_USER=root - DB_PASS=rootpass
- PHP 中读取并拼接 DSN:
$dsn = "mysql:host=" . ($_ENV['DB_HOST'] ?? 'db') . ";port=" . ($_ENV['DB_PORT'] ?? '3306') . ";dbname=" . ($_ENV['DB_NAME'] ?? 'test') . ";charset=utf8mb4"; - 不要依赖
$_SERVER或getenv(),$_ENV在 PHP 8.5 默认启用且更可靠
MySQL 容器没起来就连接会失败
PHP 容器启动时,MySQL 可能还在初始化,直接 new PDO 就会抛出 PDOException:SQLSTATE[HY000] [2002] Connection refused。
立即学习“PHP免费学习笔记(深入)”;
- 别用
depends_on单独控制启动顺序——它只等容器创建,不等 MySQL 服务就绪 - 必须配合健康检查,例如在 MySQL 服务块中加:
healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "--password=rootpass"] interval: 10s timeout: 5s retries: 5
- PHP 侧可加简单重试(非必须但保险):
for ($i = 0; $i < 5; $i++) { try { $pdo = new PDO($dsn, $user, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); break; } catch (PDOException $e) { if ($i === 4) throw $e; sleep(2); } }
字符集和严格模式要配对
PHP 8.5.5 默认启用更严格的错误报告,MySQL 若没设好字符集或 SQL 模式,容易触发警告甚至异常。
- DSN 中必须显式声明
charset=utf8mb4,否则可能存 emoji 失败或乱码 - MySQL 容器启动时建议加环境变量:
MYSQL_COLLATION=utf8mb4_unicode_ci - PHP 连接后立即执行:
$pdo->exec("SET NAMES utf8mb4")(虽 DSN 已设,但双重保险) - 开启严格模式更稳妥:
mysqld --sql-mode="STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO",可通过 MySQL 配置挂载实现
最容易被忽略的是健康检查 + 字符集组合:没健康检查,PHP 总连不上;DSN 漏了 charset=utf8mb4,中文或 emoji 插入时静默截断,查不到原因。



















