从外部容器连接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
根本性错误及修复
你存在两个核心错误:
- 容器间通信不应使用容器IP:Docker Compose会自动为所有服务创建内部网络,服务名(此处为
db)可通过内部DNS直接解析到对应容器IP,而容器IP是动态的,重启后可能变化,直接使用IP会导致连接不稳定或失败。 - 容器间连接应使用容器内部端口:
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
相关产品推荐
相关产品推荐

