Docker挂载mysqld.sock连接宿主机MySQL/MariaDB报错求助
问题根因
你的配置从基础逻辑上就错了:你启动的是一个独立的MariaDB服务容器,本身会跑自己的数据库进程,根本不是用来连接宿主机现有数据库的客户端/转发组件,所以容器入口脚本检测到没有传入初始化必需的密码参数,就会直接报你看到的错误。
就算你把宿主机的sock文件、数据目录全挂进这个容器,容器内的MariaDB进程会和宿主机上跑的MySQL进程抢sock文件锁、抢数据目录读写权,不仅连不上,还可能直接损坏宿主机上的数据库文件。
另外你提到IP直连报Connection refused,这不是IP未授权导致的——未授权的报错是Access denied for user,Connection refused的本质是宿主机MySQL没有监听Docker网桥对应的网卡地址,或是防火墙规则拦截了3306端口的请求。
正确配置方案
根据你的需求选以下任意一种方案即可:
方案1:Unix Socket 连接(无端口暴露,安全性更高)
不需要单独启动MariaDB/MySQL容器,直接给需要访问数据库的业务容器挂载宿主机的sock文件即可:
- 先确认宿主机MySQL的sock实际路径,Debian/Ubuntu系默认是
/var/run/mysqld/mysqld.sock,RHEL/CentOS系部分版本是/run/mysqld/mysqld.sock - 给宿主机上的
/var/run/mysqld目录配置权限,保证容器内运行业务进程的用户有sock文件的读写权限,临时测试可直接执行chmod 755 /var/run/mysqld - 业务容器的docker-compose配置参考如下,移除你之前写的多余mysql服务定义:
version: '3' services: your-business-service: image: 替换成你实际的业务镜像 volumes: - /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock networks: - database networks: database: external: true
- 业务代码连接数据库时,host参数直接填sock路径
/var/run/mysqld/mysqld.sock,不需要配置端口,即可通过socket通道和宿主机MySQL通信。
方案2:TCP 连接(配置简单,兼容性最好)
- 修改宿主机MySQL配置文件,在
[mysqld]配置段添加bind-address = 0.0.0.0,重启MySQL服务让配置生效,允许MySQL监听所有网卡的请求 - 登录宿主机MySQL,给业务使用的账号开放Docker网段的访问权限,比如你的Docker自定义网段
database对应的子网是172.20.0.0/16,业务用root账号、密码为your_db_pass的话,执行如下SQL:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'172.20.%.%' IDENTIFIED BY 'your_db_pass'; FLUSH PRIVILEGES;
- 检查宿主机防火墙规则,放开3306端口对Docker网桥网段的访问
- 业务容器连接数据库时,host填宿主机在
database网络上的网关IP(一般是对应子网的第一个可用IP,比如子网172.20.0.0/16的网关是172.20.0.1),端口填3306即可正常连接,不需要挂载任何sock或数据目录。
避坑提醒
- 绝对不要把宿主机的
/var/lib/mysql数据目录直接挂载给另一个运行中的MySQL/MariaDB容器,两个数据库进程同时读写同一份数据文件会直接导致数据损坏,所有业务库都可能无法恢复 - Unix Socket是主机内进程间通信的方式,不需要启动额外的数据库服务端进程,只有通信双方(这里就是宿主机MySQL和你的业务容器)能访问对应的sock文件就能通信
- 不要混淆数据库服务端和客户端的概念,你要连已经跑在宿主机上的数据库服务,就不需要再在容器里起一个新的数据库服务。
内容的提问来源于stack exchange,提问作者Majksa
相关产品推荐
相关产品推荐

