普通网友 2026-03-07 03:10 采纳率: 98.4%
浏览 0
已采纳

Docker部署Discuz时数据库连接失败如何排查?

**常见问题:Discuz容器无法连接MySQL,报错“Can't connect to MySQL server”或“Access denied”** 典型原因有三:一是Discuz容器与MySQL容器未处于同一Docker网络(如未用`--network`共网或docker-compose.yml中未声明同一network),导致域名解析失败;二是Discuz配置文件`config/config_global.php`中数据库主机名误填为`localhost`(应填MySQL服务名,如`db`);三是MySQL容器未开放3306端口、未设置允许远程访问(需确认`bind-address = 0.0.0.0`及用户host为`%`或对应容器IP),且root/自定义用户权限未通过`CREATE USER ... IDENTIFIED WITH mysql_native_password`显式指定认证插件(MySQL 8.0+默认caching_sha2_password不被Discuz兼容)。建议优先使用`docker exec -it discuz_php ping db`验证网络连通性,并用`mysql -h db -u user -p`手动测试连接。
  • 写回答

1条回答 默认 最新

  • 泰坦V 2026-03-07 03:10
    关注
    ```html

    一、现象层:错误日志与表征特征

    Discuz 容器启动后,前台白屏或后台报错 Can't connect to MySQL server(连接超时)或 Access denied for user 'root'@'172.20.0.3'(权限拒绝),PHP 错误日志中频繁出现 mysqli_connect(): (HY000/2002)PDOException: SQLSTATE[HY000] [1045]。此类错误并非 Discuz 代码缺陷,而是容器化部署中典型的“跨服务通信断裂”信号。

    二、网络层:Docker 网络拓扑验证

    • 执行 docker network inspect discuz-net 确认 discuz_phpmysql8 是否同属一个自定义 bridge 网络(非默认 bridge);
    • 检查容器内 DNS 解析:docker exec -it discuz_php ping -c 3 db —— 若失败,说明服务发现未生效;
    • 若使用 docker run 部署,必须显式添加 --network discuz-net;若用 Compose,需在 services 下统一声明 networks: [discuz-net]

    三、配置层:Discuz 数据库连接参数校准

    打开 /var/www/discuz/config/config_global.php,重点核查以下三处(严禁使用 localhost):

    配置项错误示例正确写法
    $_config['db']['1']['dbhost']'localhost''db'(MySQL 服务名,与 docker-compose.yml 中 service 名一致)
    $_config['db']['1']['dbuser']'root''discuz_user'(建议最小权限专用账户)
    $_config['db']['1']['dbpw']'123456''$2y$10$...'(密码需与 MySQL 内创建用户完全一致)

    四、MySQL 服务层:端口、绑定与认证插件兼容性

    MySQL 容器需满足以下硬性条件(以 MySQL 8.0+ 为例):

    1. 启动参数含 --bind-address=0.0.0.0 或配置文件 my.cnf 中设置 bind-address = 0.0.0.0
    2. 创建用户时必须显式指定旧版认证插件:
      CREATE USER 'discuz_user'@'%' IDENTIFIED WITH mysql_native_password BY 'StrongPass123!';
    3. 授权并刷新:GRANT SELECT,INSERT,UPDATE,DELETE ON discuz_db.* TO 'discuz_user'@'%'; FLUSH PRIVILEGES;

    五、诊断流程图:结构化排障路径

    graph TD A[Discuz 连接 MySQL 失败] --> B{能否 ping 通 db?} B -->|否| C[检查 Docker 网络 & 服务名] B -->|是| D{能否 mysql -h db -u user -p 连入?} D -->|否| E[检查 bind-address / 用户 host / 认证插件] D -->|是| F[检查 config_global.php 配置值] F --> G[验证数据库名/表前缀是否匹配] C --> H[重建 network 并重连容器] E --> I[执行 CREATE USER ... IDENTIFIED WITH mysql_native_password]

    六、进阶验证:容器内全链路抓包分析

    对高阶运维人员,推荐组合命令验证真实连接行为:

    # 在 Discuz 容器内启用 tcpdump 捕获 3306 流量
    docker exec -it discuz_php apt-get update && apt-get install -y tcpdump
    docker exec -it discuz_php tcpdump -i any port 3306 -w /tmp/mysql.pcap

    # 同时触发 Discuz 页面访问,再导出分析:
    docker cp discuz_php:/tmp/mysql.pcap ./mysql.pcap

    通过 Wireshark 分析 SYN 是否发出、MySQL Server 是否响应 SYN-ACK,可精准定位是防火墙拦截、路由丢失,还是 MySQL 进程根本未监听。

    七、生产加固建议:最小权限与配置即代码

    • 禁止在生产环境使用 root 用户连接 Discuz;应创建专用数据库 CREATE DATABASE discuz_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    • config_global.php 敏感字段通过 Docker secrets 或 env_file 注入,避免硬编码;
    • MySQL 容器健康检查应包含 mysqladmin ping -h db -u $USER -p$PASS --silent,纳入 CI/CD 部署门禁。
    ```
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 3月8日
  • 创建了问题 3月7日