
本文解析PHP项目(尤其是Symfony)在GitLab CI/CD流水线中执行PHPUnit集成测试时出现“getaddrinfo for db failed: Name or service not known”错误的根本原因,并提供从服务别名、环境变量、网络配置到测试清理的完整修复路径。
本文解析php项目(尤其是symfony)在gitlab ci/cd流水线中执行phpunit集成测试时出现“getaddrinfo for db failed: name or service not known”错误的根本原因,并提供从服务别名、环境变量、网络配置到测试清理的完整修复路径。
在CI/CD环境中运行PHP集成测试(如Symfony + Doctrine + PHPUnit)时,数据库连接失败是高频痛点。你遇到的报错:
SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo for db failed: Name or service not known
本质并非数据库服务未启动,而是DNS解析失败——CI环境根本找不到名为 db 的主机。
? 根本原因:服务别名不匹配
你的 .env.test 中配置了:
DATABASE_URL="mysql://db:db@db:3306/testdb?..."
其中 @db:3306 表示PHP应用需通过主机名 db 连接MySQL。但在GitLab CI中,services 定义的容器默认不自动注册为 db 主机名,除非显式指定 alias。
立即学习“PHP免费学习笔记(深入)”;
你当前的CI配置:
services:
- name: mariadb:10.3.11
alias: mysql # ❌ 错误:别名是 mysql,但代码里写的是 db→ 应用尝试解析 db,但CI网络中只有 mysql 可解析,导致 getaddrinfo 失败。
✅ 正确修复:将 alias 改为 db
services:
- name: mariadb:10.3.11
alias: db # ✅ 与 DATABASE_URL 中的 host 严格一致?️ 同步修正环境变量与服务配置
仅改 alias 不够,还需确保所有数据库连接参数在CI中全局一致:
variables: # ✅ 统一使用 db 作为host,与 .env.test 和 services.alias 对齐 DATABASE_URL: "mysql://root:root@db:3306/testdb?serverVersion=mariadb-10.3.11&charset=utf8mb4" # ⚠️ 移除 MYSQL_USER/MYSQL_PASSWORD 等冗余变量(Doctrine直连,不依赖MySQL内置用户变量)
同时,删除 .env.test 中硬编码的 db:db@db 用户密码(存在安全风险),改用CI注入的 DATABASE_URL —— Symfony 5.4 默认优先读取环境变量覆盖 .env.* 文件。
? 测试前验证:增加诊断步骤
在 before_script 开头加入网络连通性检查,快速定位问题:
before_script: - echo "? Testing DB connectivity..." - apk add --no-cache mysql-client # 安装MySQL客户端用于调试 - mysqladmin -h db -u root -proot ping || (echo "❌ DB connection failed"; exit 1) - echo "✅ DB is reachable" - php bin/console doctrine:database:drop --force --if-exists --env=test - php bin/console cache:clear --env=test - php bin/console doctrine:database:create --env=test - php bin/console doctrine:migrations:migrate --env=test - php bin/console doctrine:fixtures:load --env=test
⚙️ 进阶建议:提升CI稳定性与可维护性
| 问题类型 | 推荐方案 |
|---|---|
| PHP扩展缺失 | 在 before_script 中显式检查:php -m \| grep -E 'pdo_mysql|mysqli' || echo "Missing DB extension"
|
| 时区/字符集兼容 | 在 DATABASE_URL 中追加 &timezone=UTC&charset=utf8mb4,避免迁移失败 |
| 测试数据隔离 | 避免 doctrine:fixtures:load 全局污染,改用事务回滚(@dataProvider 或 setUpBeforeClass 中初始化) |
| 敏感信息防护 | 将 DATABASE_URL 设为 GitLab CI Secret Variable,而非明文写在 .gitlab-ci.yml 中 |
✅ 最终验证:一个最小可运行CI片段
phpunit:
stage: test
image: php:8.2-cli
services:
- name: mariadb:10.3.11
alias: db # 关键!必须与 DATABASE_URL host 一致
variables:
DATABASE_URL: "mysql://root:root@db:3306/testdb?serverVersion=mariadb-10.3.11&charset=utf8mb4&timezone=UTC"
before_script:
- apk add --no-cache mysql-client
- mysqladmin -h db -u root -proot ping
- composer install --no-interaction --prefer-dist
- php bin/console doctrine:database:create --env=test --if-not-exists
- php bin/console doctrine:migrations:migrate --env=test --no-interaction
script:
- vendor/bin/phpunit --testdox --colors=never? 关键总结:CI/CD中的“数据库连接失败”,90%源于服务发现不一致。务必保证
DATABASE_URL的 host、services.alias、以及容器间调用的域名三者完全统一。不要复用本地Docker Compose的网络命名逻辑到CI环境——GitLab CI的服务网络是独立、轻量且基于别名的DNS系统。
通过以上调整,你的PHPUnit集成测试将在CI中稳定连接MariaDB,真正实现“本地能过,CI必过”的可靠交付闭环。



















