Docker中php:8.1.17-apache容器连接mysql:8.0.32容器失败求助
问题背景
使用php:8.1.17-apache容器尝试连接mysql:8.0.32容器时,通过Prisma、MySQL Workbench能正常连接数据库,但PHP使用mysqli扩展连接时报错,提示No such file or directory。
现有配置
PHP容器Docker Compose配置
version: '3.8' services: vidslide-api: image: php:8.1.17-apache ports: - "80:80" volumes: - ./htdocs:/var/www/html command: > sh -c " docker-php-ext-install mysqli && \ docker-php-ext-enable mysqli && \ apache2-foreground "
MySQL容器Docker Compose配置
version: '3.8' services: vidslide-db: image: mysql:8.0.32 command: --default-authentication-plugin=mysql_native_password restart: always environment: MYSQL_ROOT_PASSWORD: *** ports: - "3306:3306" volumes: - /var/lib/vidslide_mysql-db:/var/lib/mysql volumes: mysql_data:
PHP连接代码
$conn = mysqli_connect($host, $user, $pass, $dbname); // Check connection if (!$conn) { die("Connection failed: " . mysqli_connect_error()); } echo "Connected successfully";
报错信息
Fatal error: Uncaught mysqli_sql_exception: No such file or directory in /var/www/html/index.php:14 Stack trace: #0 /var/www/html/index.php(14): mysqli_connect('localhost', 'root', '***', 'vidslide-db') #1 {main} thrown in /var/www/html/index.php on line 14
解决步骤
1. 统一Docker网络(核心问题)
当前两个容器分别在独立的Docker Compose配置中,默认处于不同的网络环境。PHP容器内的localhost指向自身容器,而非MySQL容器。
解决方法:将两个服务合并到同一个docker-compose.yml文件中,Docker会自动创建专属桥接网络,允许容器通过服务名互相访问。合并后的配置示例:
version: '3.8' services: vidslide-api: image: php:8.1.17-apache ports: - "80:80" volumes: - ./htdocs:/var/www/html command: > sh -c " docker-php-ext-install mysqli && \ docker-php-ext-enable mysqli && \ apache2-foreground " depends_on: - vidslide-db networks: - vidslide-network vidslide-db: image: mysql:8.0.32 command: --default-authentication-plugin=mysql_native_password restart: always environment: MYSQL_ROOT_PASSWORD: *** MYSQL_DATABASE: vidslide-db ports: - "3306:3306" volumes: - /var/lib/vidslide_mysql-db:/var/lib/mysql networks: - vidslide-network networks: vidslide-network: driver: bridge
2. 修改PHP连接的主机地址
将PHP代码中的$host值从localhost改为MySQL容器的服务名vidslide-db,示例:
$host = 'vidslide-db'; $user = 'root'; $pass = '***'; $dbname = 'vidslide-db'; $conn = mysqli_connect($host, $user, $pass, $dbname); // Check connection if (!$conn) { die("Connection failed: " . mysqli_connect_error()); } echo "Connected successfully";
3. 确认目标数据库存在
如果代码中指定的vidslide-db数据库未创建,可通过MySQL客户端手动创建,或在MySQL容器的环境变量中添加MYSQL_DATABASE: vidslide-db(如合并后的配置所示),容器启动时会自动生成该数据库。
4. 版本兼容性说明
php:8.1.17与mysql:8.0.32不存在版本兼容问题,且你已指定mysql_native_password认证插件,符合PHP mysqli的连接要求,因此报错与版本无关。
内容的提问来源于stack exchange,提问作者ihaveaquestion

