DATABASE_URL必须写在.env文件中,而非doctrine.yaml;其格式为mysql://user:pass@127.0.0.1:3306/db?serverVersion=8.0,需URL编码特殊字符、显式指定serverVersion,并用127.0.0.1代替localhost以避免socket错误。

DATABASE_URL 必须写在 .env,不是 doctrine.yaml
Symfony 的数据库连接配置只认 DATABASE_URL 环境变量,它必须定义在项目根目录的 .env 文件里;config/packages/doctrine.yaml 里写的只是 ORM 行为配置(比如实体映射、缓存策略),改它根本连不上库。
常见错误现象:Connection refused、SQLSTATE[HY000] [2002] No such file or directory,基本都是因为 .env 里 URL 格式不对或值为空。
-
DATABASE_URL必须带协议头,例如:mysql://user:pass@127.0.0.1:3306/mydb?serverVersion=8.0 - 本地开发别用
localhost—— MySQL 会尝试走 Unix socket,容易报No such file or directory;统一用127.0.0.1 -
serverVersion参数不可省:Doctrine 靠它决定生成什么语法,MySQL 8.0 就写8.0,5.7 就写5.7 - 密码含
@、/、:等字符时必须 URL 编码,比如pa@ss/word→pa%40ss%2Fword
Docker 容器里连宿主机 MySQL:用 host.docker.internal
当你把 Symfony 应用跑在 Docker 容器里,而 MySQL 装在宿主机上(比如 Mac/Windows 上的本地 MySQL 或 MAMP),127.0.0.1 在容器里指向的是容器自己,不是宿主机 —— 所以连不上。
正确做法是把 DATABASE_URL 中的 host 改成 host.docker.internal:
mysql://user:pass@host.docker.internal:3306/mydb?serverVersion=8.0
这个别名在 Docker Desktop(Mac/Windows)18.03+ 默认可用;Linux 用户需手动加 --add-host host.docker.internal:host-gateway 启动容器,或在 docker-compose.yml 里写:
services:
web:
# ...
extra_hosts:
- "host.docker.internal:host-gateway"注意:宿主机 MySQL 必须允许远程连接(GRANT ... ON *.* TO 'user'@'%'),且防火墙放行 3306 端口。
Docker Compose 内部服务互联:用服务名当 host
如果你用 docker-compose.yml 同时启了 Symfony(PHP)和 MySQL 容器,它们在同一个自建网络里,彼此能直接通过服务名通信。
假设你的 docker-compose.yml 里 MySQL 服务叫 db:
在 Linux 上通过 Docker 运行 OpenClaw,并使用 Tailscale 实现远程访问。⚠️ 涉及 sudo、Docker、Tailscale和凭证挂载——请先查阅安全章节...
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: myapp
web:
build: .
depends_on: [db]那么 Symfony 的 DATABASE_URL 应该写成:
mysql://root:root@db:3306/myapp?serverVersion=8.0
这里 db 是服务名,Docker 内置 DNS 会自动解析成对应容器 IP;不需要查 IP、也不需要改 hosts。
容易踩的坑:
- 确保
web服务的depends_on只控制启动顺序,不保证 MySQL 已 ready —— 第一次运行可能因 MySQL 没启好而报错,加健康检查或用 wait-for-it.sh 更稳妥 - MySQL 容器默认只监听
127.0.0.1,但 Docker 内部通信走的是容器 IP,不受影响;不用改 bind-address - 如果 Symfony 容器用的是
network_mode: host,就不能用服务名,得回退到host.docker.internal或宿主机真实 IP
doctrine:database:create 报 Access denied 别急着改配置
运行 php bin/console doctrine:database:create 失败,报 Access denied for user,大概率不是 URL 写错了,而是权限问题。
这个命令本质是用 DATABASE_URL 里的用户去连 MySQL,然后执行 CREATE DATABASE —— 它不会用 root,也不会跳过权限检查。
解决办法只有两个:
- 给
DATABASE_URL里的用户授创建库权限:GRANT CREATE ON *.* TO 'your_user'@'%'; FLUSH PRIVILEGES; - 或者绕过它:用宿主机的
mysql命令手动建库,再跑doctrine:schema:create,例如:mysql -h 127.0.0.1 -u root -proot -e "CREATE DATABASE IF NOT EXISTS myapp;"
尤其在 CI 或新环境初始化时,后者更可控 —— 因为 doctrine:database:create 不支持指定字符集和排序规则,而手动建库可以精确控制。

















