Laravel+Docker多库迁移:第二个MariaDB数据库连接超时故障
Laravel + Docker 多MariaDB数据库连接超时问题排查
环境配置
.env 文件配置
DB_CONNECTION=mysql DB_HOST=10.0.0.4 DB_PORT=3306 DB_DATABASE=x DB_USERNAME=root DB_PASSWORD= DB_CONNECTION_SECOND=mysql_second DB_HOST_SECOND=10.0.0.4 DB_PORT_SECOND=3307 DB_DATABASE_SECOND=y DB_USERNAME_SECOND=root DB_PASSWORD_SECOND=
database.php 配置
'mysql' => [ 'driver' => 'mysql', 'url' => env('DB_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'laravel'), 'username' => env('DB_USERNAME', 'root'), 'password' => env('DB_PASSWORD', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => env('DB_CHARSET', 'utf8mb4'), 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'), 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ], 'mysql_second' => [ 'driver' => 'mysql', 'host' => env('DB_HOST_SECOND', '127.0.0.1'), 'port' => env('DB_PORT_SECOND', '3307'), 'database' => env('DB_DATABASE_SECOND', 'forge'), 'username' => env('DB_USERNAME_SECOND', 'forge'), 'password' => env('DB_PASSWORD_SECOND', ''), 'unix_socket' => env('DB_SOCKET_SECOND', ''), 'charset' => env('DB_CHARSET_SECOND', 'utf8mb4'), 'collation' => env('DB_COLLATION_SECOND', 'utf8mb4_unicode_ci'), 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA_SECOND'), ]) : [], ],
Docker Compose 容器配置
db: image: mariadb:11 container_name: db hostname: mariadb volumes: - paypipol_db:/var/lib/mysql restart: always ports: - '3306:3306' environment: MYSQL_ROOT_PASSWORD: my_root_password MYSQL_DATABASE: x MYSQL_USER: root MYSQL_PASSWORD: networks: - paypipol db2: image: mariadb:11 container_name: db2 hostname: mariadb2 volumes: - paypipol_db2:/var/lib/mysql restart: always ports: - '3307:3306' # Use a different port for the second database environment: MYSQL_ROOT_PASSWORD: my_root_password MYSQL_DATABASE: y MYSQL_USER: root MYSQL_PASSWORD: networks: - paypipol
问题现象
执行第二个数据库迁移命令:
docker exec -it backend-dev php artisan migrate --database=mysql_second
出现错误:
Illuminate\Database\QueryException SQLSTATE[HY000] [2002] Connection timed out (Connection: mysql_second, SQL: select table_name as `name`, (data_length + index_length) as `size`, table_comment as `comment`, engine as `engine`, table_collation as `collation` from information_schema.tables where table_schema = 'y' and table_type in ('BASE TABLE', 'SYSTEM VERSIONED') order by table_name)
已执行排查步骤
- db和db2容器均正常运行,可通过MySQL客户端分别连接两个数据库
- 确认.env文件与database.php配置中的凭证和Docker环境变量一致
- 两个容器属于同一Docker网络,理论上可互通
排查方向与解决建议
1. Docker网络内主机名与端口使用错误
Laravel容器与数据库容器在同一Docker网络内时,不应使用宿主机IP(10.0.0.4)+ 宿主机映射端口(3307),需直接使用数据库容器的hostname或container_name,并使用容器内部端口(3306):
- 修改.env中第二个数据库配置:
DB_HOST_SECOND=mariadb2 # 对应db2容器的hostname,或直接用container_name: db2 DB_PORT_SECOND=3306
宿主机端口映射(3307:3306)仅用于外部客户端连接,容器间通信直接用容器内部端口。
2. 数据库权限配置问题
检查第二个数据库的root用户是否允许从Laravel容器所在网络访问:
- 进入db2容器执行:
docker exec -it db2 mysql -uroot -pmy_root_password - 执行权限查询:
SELECT user, host FROM mysql.user WHERE user='root';
如果root用户的host仅为localhost或127.0.0.1,需授权允许从任意主机访问:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'my_root_password' WITH GRANT OPTION; FLUSH PRIVILEGES;
3. Laravel配置缓存问题
如果之前执行过php artisan config:cache,修改.env或database.php后需清除缓存:
docker exec -it backend-dev php artisan config:clear
4. 宿主机端口冲突或防火墙限制
- 检查宿主机3307端口是否被其他进程占用:
netstat -tulpn | grep 3307 - 临时关闭宿主机防火墙(如ufw、firewalld)测试是否能连接,若恢复正常则需添加端口放行规则。
5. 数据库容器初始化异常
查看db2容器日志,确认数据库服务正常启动:
docker logs db2
检查日志中是否有启动失败、权限错误等异常信息。
内容的提问来源于stack exchange,提问作者K. Polash
相关产品推荐
相关产品推荐

