Docker Run中Bash使用差异及镜像内置环境变量的命令适配疑问
docker run Bash Commands Great question! This boils down to when and where shell variable substitution happens—whether it's your local host's shell doing the work, or the bash shell inside your Docker container. Let's break this down step by step.
First Scenario: Passing Envs with -e and Using Double Quotes
When you ran:
docker run --rm -i -e dbuser=root -e dbpass=xfdZdfd -e dbhost=abc.com -e dbport=32 docker.abc.com/tools/mysql-client bash -c "mysqldump -u$dbuser -p$dbpass -h$dbhost -P$dbport db1 > db1.sql"
The double quotes around your bash -c command tell your local host's shell to first parse and substitute any $variable references before passing the command to Docker.
For this to work, your local shell must have had those dbuser, dbpass, etc., variables defined (either via export or in your shell session). Your host shell replaced $dbuser with root, $dbpass with xfdZdfd, and so on, then sent the fully expanded command to the container's bash to execute. The -e flags you passed to Docker were actually redundant here—you were using your host's variables, not the container's.
Second Scenario: Built-in Envs via Dockerfile and Using Single Quotes
Once you baked those environment variables into your image with ENV in the Dockerfile, those variables only exist inside the container's shell environment.
If you tried using double quotes again, your local host shell would still try to substitute $dbuser—but since your host doesn't have that variable defined, it would replace it with an empty string. The command that reached the container would look like:
mysqldump -u -p -h -P db1 > db1.sql
Which obviously fails because MySQL can't authenticate without a username/password.
By switching to single quotes, you're telling your local shell: "Don't touch anything inside these quotes—pass it exactly as-is to the container." Now the container's bash shell gets the unmodified command string, and since it has the dbuser, dbpass, etc., variables set via ENV, it does the substitution itself. The result is a properly formed mysqldump command that uses the container's environment variables.
Key Takeaway
- Double quotes: Variable substitution happens on your local host before the command reaches the container. Use this if you want to inject host-side variables into the container command.
- Single quotes: Variable substitution is deferred to the container's shell. Use this when you want to use variables that exist only inside the container (like those set via
ENVin a Dockerfile).
内容的提问来源于stack exchange,提问作者richard

