Docker: MySQL 容器绑定主机 mysqld 套接字
Docker: MySQL container bind host mysqld socket
我正在使用 Docker 19.03.8 并且想要设置两个容器:
- 第一个是 MySQL 容器,它从主机绑定挂载 mysqld 套接字。
- 第二个是PHP容器,需要通过MySQL容器访问数据库。
两个容器通过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
根据您展示的设置,您将遇到以下事件序列:
- Docker 尝试设置
database
容器。
- Docker 发现
/var/run/mysqld/mysqld.sock
在主机上不存在,因此它在那里创建一个空目录并将其挂载到容器中。
- 当 MySQL 守护程序启动时,它会尝试在
/tmp/mysql.sock
处创建套接字,但那里已经有一个(空)目录。
一般来说,最好避免尝试通过文件系统在容器之间进行通信。除了这些复杂情况之外,还经常存在用户权限问题,并且此设置限制了您在 Docker Swarm 和 Kubernetes 等多主机设置上 运行 的能力。
我正在使用 Docker 19.03.8 并且想要设置两个容器:
- 第一个是 MySQL 容器,它从主机绑定挂载 mysqld 套接字。
- 第二个是PHP容器,需要通过MySQL容器访问数据库。
两个容器通过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
根据您展示的设置,您将遇到以下事件序列:
- Docker 尝试设置
database
容器。 - Docker 发现
/var/run/mysqld/mysqld.sock
在主机上不存在,因此它在那里创建一个空目录并将其挂载到容器中。 - 当 MySQL 守护程序启动时,它会尝试在
/tmp/mysql.sock
处创建套接字,但那里已经有一个(空)目录。
一般来说,最好避免尝试通过文件系统在容器之间进行通信。除了这些复杂情况之外,还经常存在用户权限问题,并且此设置限制了您在 Docker Swarm 和 Kubernetes 等多主机设置上 运行 的能力。