You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从外部容器连接Docker化MySQL数据库超时,求助排查问题

Docker容器间MySQL连接超时问题解决

问题场景

使用以下docker-compose.yml部署了PHP+Apache、phpMyAdmin和MySQL容器环境:

version: '3.8'
services:
    php-apache-environment:
        container_name: php-apache
        build:
            context: ./php
            dockerfile: Dockerfile
        depends_on:
            - db
        volumes:
            - ./php/src:/var/www/html/
        ports:
            - 8000:80
    phpmyadmin:
        image: phpmyadmin/phpmyadmin
        ports:
            - '8080:80'
        restart: always
        environment:
            PMA_HOST: db
        depends_on:
            - db
    db:
        container_name: db
        image: mysql
        restart: always
        environment:
            MYSQL_ROOT_PASSWORD: MYSQL_ROOT_PASSWORD
            MYSQL_DATABASE: MYSQL_DATABASE
            MYSQL_USER: MYSQL_USER
            MYSQL_PASSWORD: MYSQL_PASSWORD
        ports:
            - "9906:3306"

从PHP容器运行连接测试代码时,使用docker inspect获取的MySQL容器IP(192.168.208.2)和宿主机映射端口9906,出现超时错误:

$conn = new mysqli(192.168.208.2, 'MYSQL_USER', 'MYSQL_PASSWORD', 'MYSQL_DATABASE', 9906);
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
} else {
    echo "Connected to MySQL server successfully!";
}

错误信息:

Warning: mysqli::__construct(): (HY000/2002): Connection timed out in /var/www/html/index.php on line 12

根本性错误及修复

你存在两个核心错误:

  1. 容器间通信不应使用容器IP:Docker Compose会自动为所有服务创建内部网络,服务名(此处为db)可通过内部DNS直接解析到对应容器IP,而容器IP是动态的,重启后可能变化,直接使用IP会导致连接不稳定或失败。
  2. 容器间连接应使用容器内部端口:9906是宿主机映射到MySQL容器的端口,容器间通信直接访问容器内部的3306端口即可,无需经过宿主机的端口映射。

修改后的连接代码

// 使用服务名db作为主机地址,端口用容器内部的3306
$conn = new mysqli('db', 'MYSQL_USER', 'MYSQL_PASSWORD', 'MYSQL_DATABASE', 3306);
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
} else {
    echo "Connected to MySQL server successfully!";
}

额外注意事项

  • 确保docker-compose.yml中的环境变量(如MYSQL_USER、MYSQL_PASSWORD)替换为实际有效值,不要保留占位符。
  • depends_on仅保证容器启动顺序,不保证MySQL服务完全就绪。如果仍有连接问题,可在代码中添加重试逻辑,或为MySQL服务添加健康检查:
db:
    # 其他配置不变
    healthcheck:
        test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
        timeout: 20s
        retries: 10

内容的提问来源于stack exchange,提问作者Aidan Campbell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 07:03:30