node.js 使用 docker run 命令将参数传递给 Dockerfile 中的 CMD
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40873165/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Use docker run command to pass arguments to CMD in Dockerfile
提问by Jaaaaaaay
I'm new to Docker and I'm having a hard time to setup the docker container as I want. I have a nodejs app can take two parameters when start. For example, I can use
我是 Docker 的新手,我很难按照自己的意愿设置 Docker 容器。我有一个 nodejs 应用程序可以在启动时使用两个参数。例如,我可以使用
node server.js 0 dev
node server.js 0 dev
or
或者
node server.js 1 prod
node server.js 1 prod
to switch between production mode and dev mode and determine if it should turn the cluster on. Now I want to create docker image with arguments to do the similar thing, the only thing I can do so far is to adjust the Dockerfile to have a line
在生产模式和开发模式之间切换并确定是否应该打开集群。现在我想用参数来创建 docker 镜像来做类似的事情,到目前为止我唯一能做的就是调整 Dockerfile 以有一条线
CMD [ "node", "server.js", "0", "dev"]
CMD [ "node", "server.js", "0", "dev"]
and
和
docker build -t me/app .to build the docker.
docker build -t me/app .构建泊坞窗。
Then docker run -p 9000:9000 -d me/appto run the docker.
然后docker run -p 9000:9000 -d me/app运行docker。
But If I want to switch to prod mode, I need to change the Dockerfile CMD to be
但是如果我想切换到 prod 模式,我需要将 Dockerfile CMD 更改为
CMD [ "node", "server.js", "1", "prod"],
CMD [ "node", "server.js", "1", "prod"],
and I need to kill the old one listening on port 9000 and rebuild the image. I wish I can have something like
我需要杀死在端口 9000 上侦听的旧的并重建映像。我希望我能有类似的东西
docker run -p 9000:9000 environment=dev cluster=0 -d me/app
docker run -p 9000:9000 environment=dev cluster=0 -d me/app
to create an image and run the nodejs command with "environment" and "cluster" arguments, so I don't need to change the Dockerfile and rebuild the docker any more. How can I accomplish this?
创建映像并使用“environment”和“cluster”参数运行 nodejs 命令,因此我不再需要更改 Dockerfile 并重建 docker。我怎样才能做到这一点?
回答by VonC
Make sure your Dockerfile declares an environment variable with ENV:
确保您的Dockerfile声明环境变量有ENV:
ENV environment default_env_value
ENV cluster default_cluster_value
The ENV <key> <value>form can be replaced inline.
的ENV <key> <value>形式可以代替内联。
Then you can pass an environment variable with docker run
docker run -p 9000:9000 -e environment=dev -e cluster=0 -d me/app
Or you can set them through your compose file:
或者您可以通过您的撰写文件设置它们:
node:
environment:
- environment=dev
- cluster=0
Your Dockerfile CMDcan use that environment variable, but, as mentioned in issue 5509, you need to do so in a sh -cform:
您的 DockerfileCMD可以使用该环境变量,但是,如issue 5509 中所述,您需要以一种sh -c形式这样做:
CMD ["sh", "-c", "node server.js ${cluster} ${environment}"]
The explanation is that the shell is responsible for expanding environment variables, not Docker. When you use the JSON syntax, you're explicitly requesting that your command bypass the shell and be executed directly.
解释是shell负责扩展环境变量,而不是Docker。当您使用JSON 语法时,您明确要求您的命令绕过 shell 并直接执行。
Same idea with Builder RUN(applies to CMDas well):
与Builder RUN相同的想法(也适用于CMD):
Unlike the shell form, the exec form does not invoke a command shell.
This means that normal shell processing does not happen.For example,
RUN [ "echo", "$HOME" ]will not do variable substitution on$HOME. If you want shell processing then either use the shell form or execute a shell directly, for example:RUN [ "sh", "-c", "echo $HOME" ].When using the exec form and executing a shell directly, as in the case for the shell form, it is the shell that is doing the environment variable expansion, not docker.
与 shell 形式不同,exec 形式不调用命令 shell。
这意味着不会发生正常的 shell 处理。例如,
RUN [ "echo", "$HOME" ]不会对 进行变量替换$HOME。如果你想要 shell 处理,那么要么使用 shell 形式,要么直接执行 shell,例如:RUN [ "sh", "-c", "echo $HOME" ].当使用 exec 形式并直接执行 shell 时,就像 shell 形式一样,是 shell 进行环境变量扩展,而不是 docker。
回答by R0MANARMY
Another option is to use ENTRYPOINTto specify that nodeis the executable to run and CMDto provide the arguments. The docs have an example in Exec form ENTRYPOINT example.
另一个选项是用于ENTRYPOINT指定node要运行的可执行文件并CMD提供参数。文档中有一个Exec 形式的示例 ENTRYPOINT example。
Using this approach, your Dockerfile will look something like
使用这种方法,您的 Dockerfile 将类似于
FROM ...
ENTRYPOINT [ "node", "server.js" ]
CMD [ "0", "dev" ]
Running it in dev would use the same command
在 dev 中运行它会使用相同的命令
docker run -p 9000:9000 -d me/app
and running it in prod you would pass the parameters to the run command
并在 prod 中运行它,您会将参数传递给 run 命令
docker run -p 9000:9000 -d me/app 1 prod
You may want to omit CMDentirely and always pass in 0 devor 1 prodas arguments to the run command. That way you don't accidentally start a prod container in dev or a dev container in prod.
您可能希望CMD完全省略并始终传入0 dev或1 prod作为运行命令的参数。这样你就不会意外地在 dev 中启动一个 prod 容器或在 prod 中启动一个 dev 容器。
回答by Paul
The typical way to do this in Docker containers is to pass in environment variables:
在 Docker 容器中执行此操作的典型方法是传入环境变量:
docker run -p 9000:9000 -e NODE_ENV=dev -e CLUSTER=0 -d me/app
回答by Ryan Augustine
Going a bit off topic, build arguments exist to allow you to pass in arguments at build time that manifest as environment variables for use in your docker image build process:
有点偏离主题,存在构建参数以允许您在构建时传递参数,这些参数显示为环境变量,以在您的 docker 映像构建过程中使用:
$ docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 .

