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

Docker环境下php8.1-fpm-alpine无法连接mysql8.0服务问题求助

问题描述

如果我的提问存在表述不够准确的地方还请谅解,这是我首次在此平台提问。
我当前正在搭建Docker服务栈,遇到了PHP容器(基于php:8.1-fpm-alpine镜像)与MySQL服务端(基于mysql:8.0镜像)的连接故障。

现有配置

  • PHP镜像构建所用Dockerfile:
FROM php:8.1-fpm-alpine

# 安装连接MySQL所需的PHP PDO扩展
RUN docker-php-ext-install mysqli pdo pdo_mysql

WORKDIR /var/www/html/web-root
  • MySQL镜像构建所用Dockerfile:
FROM mysql:8.0

EXPOSE 3307
  • 宿主机连接验证:通过Beekeeper-Studio使用以下参数可正常连接MySQL服务:
host: 127.0.0.1
port: 3307
user: root
password: 空
  • PHP测试连接代码:
<?php 

require_once "/logs/log.php";


$MYSQL_ADDRESS = "127.0.0.1"; // 注释标注127.0.0.1对应mysql容器IP 172.22.0.5
$MYSQL_DATABASE = "version_db";
$MYSQL_USER = "root";
$MYSQL_PASS = "";
$MYSQL_PORT = "3307";
$MYSQL_DSN = "mysql:host=${MYSQL_ADDRESS};port=${MYSQL_PORT};charset=UTF8;dbname=${MYSQL_DATABASE}";


$logger = new Log();


$logger->log("Update Databases!");


if (!in_array('pdo_mysql', get_loaded_extensions())) {
    $logger->log("pdo_mysql not loaded!");
    exit("pdo_mysql not loaded!");
}

$logger->log("MYSQL_DSN: " . $MYSQL_DSN);

try {
    $pdo = new PDO($MYSQL_DSN, $MYSQL_USER, $MYSQL_PASS, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::MYSQL_ATTR_FOUND_ROWS => TRUE]);
} catch (PDOException $e) {
    $logger->log("No connection to database possible");
    $logger->log($e);
    exit("No connection to database possible");
}

$logger->log("connected to database");

运行测试代码后日志记录数据库连接失败,报错为连接被拒绝。


故障原因与修复方案

核心问题点

你踩了三个Docker容器互联的典型配置错误:

  1. 数据库地址配置错误
    PHP容器内的127.0.0.1指向PHP容器自身的回环接口,既不是宿主机地址也不是MySQL容器地址。你注释里写的172.22.0.5是Docker临时分配的容器IP,容器重启后会发生变化,不能硬编码使用。
  2. 连接端口配置错误
    MySQL Dockerfile里的EXPOSE 3307是无效配置:MySQL官方镜像内部服务默认监听3306端口,你能在宿主机通过3307端口连上,是因为启动容器时做了-p 3307:3306的端口映射,这个映射规则仅对宿主机访问容器生效。同网络下的容器之间通信,必须使用MySQL容器内部实际监听的3306端口。
  3. MySQL账号权限配置错误
    MySQL8.0官方镜像默认root用户仅允许从容器本地localhost登录,未开放其他IP的访问权限,即使地址和端口配置正确,跨容器访问也会被权限规则拦截,同时MySQL8.0默认的caching_sha2_password认证插件也可能和旧版pdo_mysql扩展存在兼容问题。

分步修复

  1. 配置容器网络
    不要使用默认的bridge网络,创建自定义桥接网络,两个容器启动时都加入该网络,给MySQL容器设置固定服务名,Docker内置DNS会自动把服务名解析到对应容器IP。
    docker启动命令参考:
# 创建自定义网络
docker network create app-stack

# 启动MySQL容器,指定服务名、所属网络、端口映射和初始化参数
docker run -d \
  --name mysql \
  --network app-stack \
  -p 3307:3306 \
  -e MYSQL_ALLOW_EMPTY_PASSWORD=yes \
  -e MYSQL_DATABASE=version_db \
  mysql:8.0

# 启动PHP容器,加入同一个网络
docker run -d \
  --name php-fpm \
  --network app-stack \
  -v /local/code/path:/var/www/html/web-root \
  your-custom-php-image:latest

如果使用docker-compose部署,同一compose文件下的服务默认加入同一个网络,直接用服务名做主机名即可,无需额外创建网络。
2. 修改PHP数据库连接参数
把代码里的连接配置调整为:

$MYSQL_ADDRESS = "mysql"; // 和MySQL容器的服务名/网络别名保持一致
$MYSQL_PORT = "3306"; // 填写MySQL容器内部实际监听端口
  1. 开放MySQL远程访问权限
    进入MySQL容器,登录MySQL控制台后执行以下命令,放开root用户的远程访问限制并切换兼容的认证插件(生产环境建议单独创建业务账号并限制访问源,不要直接用root):
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '';
FLUSH PRIVILEGES;
  1. 清理无效配置
    删掉MySQL Dockerfile里的EXPOSE 3307行,EXPOSE只是镜像元数据标记,不会修改服务实际监听端口,保留只会产生误导。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:09:15