从docker container php:8.1.17-apache到docker container mysql:8.0.32的MySQL连接不起作用

mwngjboj  于 2023-03-24  发布在  Apache
关注(0)|答案(2)|浏览(103)

我正在尝试从这个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
      "

这个docker容器:

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:

我可以用prisma和mysql workbench连接到mysql服务器,但不能用php。
当我尝试连接mysqli时:

$conn = mysqli_connect($host, $user, $pass, $dbname);

// Check connection
if (!$conn) {
    die("Connection failed: " . mysqli_connect_error());
}
echo "Connected successfully";

我得到:致命错误:未捕获的mysqli_sql_异常:/var/www/html/index.php:14堆栈跟踪:Copyright © 2018 - 2019 www.jsjsj.com版权所有Copyright © 2018 - 2019 www. jsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsjsj
mysqli config from phpinfo();

我不明白错误信息。
我需要做些什么才能让它工作?版本不兼容吗?

dbf7pr2w

dbf7pr2w1#

这里有很多东西要拆。
1.将每个docker-compose.yml视为不同的“项目”。对于每个项目,docker-compose将创建自己的虚拟网络。如果每个项目中没有额外的配置,这些虚拟网络将无法相互通信

  • ports:部分中的声明将端口 out Map到主机的localhost:port,但仅此而已。
  • 注意:实际上所有接口现在都将侦听该端口,而不仅仅是本地端口。
  • “localhost”仅对单个容器是本地的。每个容器都有自己的,并且它们也不是宿主机的“localhost”。
  • 大多数mysql驱动程序[包括PHP的]将名称localhostMap到本地unix套接字,只有当您在与Mysql相同的主机[或容器]上运行代码时才可用。

4是为什么你在连接时会得到奇怪的“文件未找到”错误,因为它找不到套接字文件,其他一切都是为什么它无论如何都不会工作。

简单的解决方案是将这两个服务合并到一个docker-compose.yml中,然后使用mysql服务的主机名而不是localhost。

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
      "
  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:

Docker-compose为每个服务创建本地DNS名称,因此您的mysql主机名将是vidslide-db而不是localhost
此外,你不希望每次容器启动时都安装任何东西,除非你真的喜欢每次容器启动时都等待扩展编译。为此,你需要构建自己的镜像,其中包括此镜像,而Docker-compose可以轻松地按需构建。
将其作为Dockerfile-php添加到与docker-compose.yml相同的目录中:

FROM php:8.1.17-apache

RUN docker-php-ext-install mysqli && \
    docker-php-ext-enable mysqli

vidslide-api服务更改为:

vidslide-api:
    build:
      dockerfile: Dockerfile-php
      context: ./
    ports:
      - "80:80"
    volumes:
      - ./htdocs:/var/www/htm
kpbwa7wx

kpbwa7wx2#

在这种情况下,localhost实际上是 container 而不是 host。因此,连接失败(因为PHP容器没有托管MySQL数据库)。
要在Docker Desktop中使用主机,请使用host.docker.internal作为IP。
如果您希望此解决方案也能在 *nix上工作,请参考this answer
对于生产示例,您肯定应该使用docker网络将容器连接在一起,并使用link s或hostname访问数据库。

相关问题