Docker: MySQL 容器绑定主机 mysqld 套接字

Docker: MySQL container bind host mysqld socket

我正在使用 Docker 19.03.8 并且想要设置两个容器:

两个容器通过networks语句共享同一个网络。 (我无法将 mysqld 套接字直接绑定到 PHP 容器中,因为 MySQL 版本不同,因此 MySQL 容器)。

这是我的docker-compose.yml文件:

...
database:
  build: .
  volumes:
    - /var/run/mysqld/mysqld.sock:/tmp/mysql.sock
...

Docker文件 MySQL:

FROM mysql:8.0.20
COPY my.cnf /etc/mysql/my.cnf

并且 my.cnf 文件包含:

...
[mysql]
socket = /tmp/mysql.sock

[mysqld]
socket = /tmp/mysql.sock
...

不幸的是,我从 MySQL 容器收到此错误消息:

2020-05-20T11:30:04.708067Z 0 [ERROR] [MY-010270] [Server] Can't start server : Bind on unix socket: Address already in use
2020-05-20T11:30:04.708406Z 0 [ERROR] [MY-010258] [Server] Do you already have another mysqld server running on socket: /tmp/mysql.sock ?
2020-05-20T11:30:04.709083Z 0 [ERROR] [MY-010119] [Server] Aborting

如果我在 my.cnf[mysqld] 部分中遗漏了 socket = /tmp/mysql.sock,MySQL 容器启动时没有错误.但是,如果我随后尝试从 PHP 容器 (mysql -h <what I specified in the networks statement> -u <user> -p <password>) 连接到数据库,我只会得到一个空数据库。所以我假设它使用默认套接字 (/var/run/mysqld/mysqld.sock).

我不明白为什么这不起作用,如果有人能给我提示,我将不胜感激。

您应该为此使用 TCP 连接。配置 PHP 容器以连接到数据库容器的 Compose 服务名称 (database) 和默认 MySQL 端口 (3306)。不要在这里尝试使用 Unix 套接字。

此设置应适用于开箱即用的 mysql:8 和 Docker Compose 配置。您不需要自定义 my.cnf 或 Compose networks:container_name:links: 或其他选项。


您显示的设置中的重要细节是 MySQL 守护进程必须自己创建套接字文件。如果您真的想使用 Unix 套接字来执行此操作,则需要绑定挂载包含套接字文件的目录;您不能绑定安装套接字本身。 (原则上您也可以在这里使用命名卷。)

# Not the preferred path: mount a directory instead of a file
volumes:
  - ./shared_tmp:/tmp

根据您展示的设置,您将遇到以下事件序列:

  1. Docker 尝试设置 database 容器。
  2. Docker 发现 /var/run/mysqld/mysqld.sock 在主机上不存在,因此它在那里创建一个空目录并将其挂载到容器中。
  3. 当 MySQL 守护程序启动时,它会尝试在 /tmp/mysql.sock 处创建套接字,但那里已经有一个(空)目录。

一般来说,最好避免尝试通过文件系统在容器之间进行通信。除了这些复杂情况之外,还经常存在用户权限问题,并且此设置限制了您在 Docker Swarm 和 Kubernetes 等多主机设置上 运行 的能力。