Windows环境下Docker MySQL无法使用$MYSQL_ROOT_PASSWORD执行命令
这个问题核心在于Windows PowerShell的引号和变量解析规则和Linux shell完全不同,你踩的几个坑都是因为没适配PowerShell的特性,我给你逐个拆解并给出解决方案:
为什么你的几个命令都失败了?
1. 直接使用-p$MYSQL_ROOT_PASSWORD的命令
docker exec mysql-container mysql -u root -p$MYSQL_ROOT_PASSWORD -e 'show databases;'
如果$MYSQL_ROOT_PASSWORD是容器内部的环境变量(比如你启动容器时通过-e设置的),PowerShell根本不知道这个变量的存在,会直接把它解析为空值,所以传给MySQL的密码是空,自然报权限错误。如果是PowerShell会话里的变量,问题也出在PowerShell对单引号外变量的解析逻辑,但显然你这里是容器内的变量。
2. 使用双引号包裹sh -c内容的命令
docker exec mysql-container sh -c "mysql -u root -p$MYSQL_ROOT_PASSWORD -e 'show databases;'"
PowerShell会优先解析双引号里的$MYSQL_ROOT_PASSWORD,如果PowerShell里没有这个变量,就会替换成空字符串,传到容器的sh里时,-p后面没有密码,所以MySQL提示你输入密码,最终报using password: NO的错误。
3. 使用单引号包裹sh -c内容的命令
docker exec mysql-container sh -c 'mysql -u root -p$MYSQL_ROOT_PASSWORD -e "show databases;"'
这里PowerShell确实不会解析$MYSQL_ROOT_PASSWORD,会把它原封不动传给容器的sh,但问题出在引号嵌套:容器内的sh处理双引号时,会把"show databases;"里的内容异常解析,导致SQL语句被截断,最终报语法错误。
正确的解决方案
分两种场景处理:
场景1:$MYSQL_ROOT_PASSWORD是PowerShell会话中的变量
如果你已经在PowerShell里定义了这个变量(比如$MYSQL_ROOT_PASSWORD = 'secret'),直接用双引号包裹变量,确保PowerShell解析后完整传递密码:
docker exec mysql-container mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e 'show databases;'
注意-p和密码之间不要加空格,MySQL的-p参数后面可以直接跟密码,不需要空格分隔。
场景2:$MYSQL_ROOT_PASSWORD是容器内部的环境变量
这时候需要让容器内的sh去解析这个变量,必须阻止PowerShell解析$符号,有两种可靠方式:
方式1:用反引号`转义$符号
PowerShell里的反引号是专属转义符,用它转义$后,PowerShell会把$当成普通字符传给容器的sh,由sh解析容器内的环境变量:
docker exec mysql-container sh -c "mysql -u root -p`$MYSQL_ROOT_PASSWORD -e 'show databases;'"
方式2:用单引号包裹整个sh -c命令,内部单引号转义
PowerShell里单引号内部的单引号需要写成两个单引号来转义,这样整个命令会原封不动传给容器的sh:
docker exec mysql-container sh -c 'mysql -u root -p$MYSQL_ROOT_PASSWORD -e ''show databases;'''
容器内的sh收到命令后,会正确解析$MYSQL_ROOT_PASSWORD,同时''show databases;''会被解析成'show databases;',符合MySQL的语法要求。
额外提醒
记住PowerShell的核心引号规则:
- 双引号
":会解析内部的变量、转义字符(比如``n`是换行) - 单引号
':完全原样输出,不解析任何内容 - 要让容器内的shell处理变量,必须阻止PowerShell提前解析
$,要么转义,要么用单引号包裹整个命令字符串。
内容的提问来源于stack exchange,提问作者Nicolas




