无法使用PHP PDO连接运行在Docker上的本地MariaDB。

4
我在本地使用 Docker-compose 来运行 MariaDB、PHP-FPM 和 Nginx 进行开发。通过在浏览器中访问 http://localhost:8080/,可以成功地访问 Nginx 提供的网页页面。同时,我还能够在本地使用 TablePlus 作为 GUI 数据库浏览器,通过主机 127.0.0.1、端口 8889 成功连接到数据库(这个用户是 root,密码也是 root,但是奇怪的是,如果将 MYSQL_USER 和 MYSQL_PASSWORD 设置为其他用户名时,Docker-compose 将不能正确地捕获这些环境变量)。

然而,当我尝试使用以下 PHP 代码来连接数据库,并使用相同的凭据时:

$db = new PDO('mysql:host=localhost;port=8889;dbname=words', 'root', 'root');

我遇到了Error: SQLSTATE[HY000] [2002] No such file or directory的问题。

编辑:当我使用以下代码时:

$db = new PDO('mysql:host=127.0.0.1;port=8889;dbname=words', 'root', 'root');

我收到了一个错误信息:Error: SQLSTATE[HY000] [2002] Connection refused

为什么会出现这个错误呢?

以下是我的Docker Compose文件:

version: "3"

services:

  mariadb:
    image: mariadb:10.5
    container_name: mariadb-10.5
    restart: unless-stopped
    ports:
      # port 3306 is the default port for mariadb, forwarded to 8889 on the local machine
      - 8889:3306
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}

  php-fpm:
    image: bitnami/php-fpm:7.4
    container_name: phpfpm-7.4
    restart: unless-stopped
    ports:
      - 9000:9000
    volumes:
      - ${WWW_DOCUMENT_ROOT}:/app

  nginx:
    image: bitnami/nginx:1.20
    container_name: nginx-1.20
    restart: always
    ports:
      - 8080:8080
    volumes:
      - ./nginx/logs:/opt/bitnami/nginx/logs/
      - ./nginx/server-blocks/default.conf:/opt/bitnami/nginx/conf/server_blocks/default.conf:ro
      - ${WWW_DOCUMENT_ROOT}:/app
    depends_on:
      - mariadb
      - php-fpm

)


1
当主机名为“localhost”时,PHP PDO使用Unix域套接字而不是TCP套接字。请尝试改用“127.0.0.1”。 - Tim Roberts
抱歉,我忘了说我也尝试过使用127.0.0.1。我已经编辑了我的问题。 - bolino
数据库中的用户凭据与客户端user@localhostuser@10.%相关联,例如产生不同的响应。防火墙、Selinux可能需要进一步缩小范围,我也不了解任何Docker方面的内容。 - ficuscr
1
请参考此问题,容器之间的连接忽略了端口,因此请使用3306端口,并将主机名设置为mariadb容器名称“mariadb-10.5”。MYSQL_USER会创建一个$MYSQL_USER@%用户,因此可以访问该用户。 - danblack
1
很高兴能帮忙。只是时间太紧,无法做得更好。你可以自己来做。 - danblack
显示剩余3条评论
1个回答

4

正如@danblack所回答的那样,因为连接到数据库是从一个Docker容器内部到另一个容器内部进行的:

  1. 容器之间的连接始终使用未映射的端口。 因此,连接到DB容器需要使用内部的MariaDB标准端口3306,而不是重映射的、暴露的8889端口。

  2. DB的主机名必须是DB容器名称(在这种情况下为MariaDB容器名称mariadb-10.5),而不是127.0.0.1localhost

因此,总的来说,PHP/PDO连接对象变成了:

$db = new PDO('mysql:host=mariadb-10.5;dbname=words', 'root', 'root');

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接