Docker Compose部署的MySQL用localhost连接报错,127.0.0.1正常的原因?
MySQL Docker Compose连接问题解析
问题描述
通过Docker Compose部署MySQL后,使用以下两个命令能正常连接:
mysql --host=127.0.0.1 --user=root --password=team6 --port=53366mysql --host=0.0.0.0 --user=root --password=team6 --port=53366
但执行mysql --host=localhost --user=root --password=team6 --port=53366时,报错:
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
最终目标是让这段Node.js代码正常运行:
con = await mysql.createConnection({ host: 'localhost', port: '53366', //We need to consider adding new users user: 'root', password: 'team6', database: 'Yahtzee', });
使用的Docker Compose文件如下:
# Compose file for creating a database named Yahtzee in a mysql container version: '3.8' services: team6db: image: mysql/mysql-server:latest restart: always environment: MYSQL_ROOT_PASSWORD: team6 MYSQL_DATABASE: Yahtzee MYSQL_ROOT_HOST: '%' volumes: - team6db:/var/lib/mysql - ./Initdb.sql:/docker-entrypoint-initdb.d/Initdb.sql - ./InsertSampleGameRecords.sql:/docker-entrypoint-initdb.d/InsertSampleGameRecords.sql ports: - '53366:3306' team6phpmyadmin: image: phpmyadmin/phpmyadmin:latest restart: always depends_on: - team6db environment: PMA_HOST: team6db PMA_USER: root PMA_PASSWORD: team ports: - '50086:80' volumes: team6db:
原因解析
- 连接方式差异:MySQL客户端指定
host=localhost时,默认优先使用Unix套接字连接,而非TCP/IP端口;而127.0.0.1或0.0.0.0会强制触发TCP/IP连接。 - Docker隔离性:MySQL运行在容器内,宿主机的Unix套接字和容器内的完全独立。用
localhost连接时,宿主机客户端会尝试找本地的MySQL套接字,而非容器内的,自然无法匹配到正确的服务,进而抛出权限错误。 - 用户权限不匹配:你设置了
MYSQL_ROOT_HOST='%',这仅授权root用户通过TCP/IP从任意主机连接,但MySQL中root@localhost是专门对应套接字连接的用户,这个用户要么没设置密码,要么在你指定MYSQL_ROOT_HOST='%'时未被正确创建。
解决方法
方法1:修改代码,强制TCP/IP连接
直接把代码中的host: 'localhost'改为host: '127.0.0.1',强制使用TCP/IP连接映射的53366端口,最直接有效:
con = await mysql.createConnection({ host: '127.0.0.1', port: '53366', user: 'root', password: 'team6', database: 'Yahtzee', });
方法2:映射容器套接字到宿主机
在Docker Compose的team6db服务中添加卷映射,把容器内的MySQL套接字目录同步到宿主机:
services: team6db: # 保留原有配置 volumes: - team6db:/var/lib/mysql - ./Initdb.sql:/docker-entrypoint-initdb.d/Initdb.sql - ./InsertSampleGameRecords.sql:/docker-entrypoint-initdb.d/InsertSampleGameRecords.sql - ./mysql-socket:/var/run/mysqld # 新增套接字映射
然后在Node.js代码中指定套接字路径:
con = await mysql.createConnection({ host: 'localhost', port: '53366', user: 'root', password: 'team6', database: 'Yahtzee', socketPath: './mysql-socket/mysqld.sock' # 指定套接字路径 });
注意:先在宿主机创建./mysql-socket目录,并确保权限足够,避免容器无法写入。
方法3:创建支持套接字连接的root用户
进入MySQL容器,手动创建root@localhost用户并授权:
- 进入容器:
docker exec -it team6db bash(替换为你的容器名称/ID) - 登录MySQL:
mysql -uroot -pteam6 - 执行SQL:
CREATE USER 'root'@'localhost' IDENTIFIED BY 'team6'; GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION; FLUSH PRIVILEGES;
此方法需要配合方法2的套接字映射,否则宿主机客户端仍无法访问容器内的套接字。
内容的提问来源于stack exchange,提问作者Ilan Rosenbaum
相关产品推荐
相关产品推荐

