使用docker run命令将parameter passing给Dockerfile中的CMD

我是Docker的新手,我很难按照自己的意愿设置Docker容器。 我有一个nodejs应用程序可以采取两个参数,当启动。 例如,我可以使用

node server.js 0 dev

要么

node server.js 1 prod

在生产模式和开发模式之间切换,并确定是否应打开群集。 现在我想用参数创builddocker映像来做类似的事情,我目前唯一能做的事情就是调整Dockerfile来创build一个行

CMD [ "node", "server.js", "0", "dev"]

docker build -t me/app . build造docker。

然后docker run -p 9000:9000 -d me/app来运行docker。

但是,如果我想切换到prod模式,我需要将Dockerfile CMD更改为

CMD [ "node", "server.js", "1", "prod"]

我需要杀掉在9000端口听的老人并重build图像。 我希望我能有类似的东西

docker run -p 9000:9000 environment=dev cluster=0 -d me/app

创build一个映像并运行带有“environment”和“cluster”参数的nodejs命令,所以我不需要更改Dockerfile并重新构builddocker。 我怎样才能做到这一点?

确保你的Dockerfile 用ENV声明一个环境variables:

 ENV environment default_env_value ENV cluster default_cluster_value 

可以内联replace ENV <key> <value>表单。

然后你可以通过docker run来传递一个环境variables

 docker run -p 9000:9000 -e environment=dev -e cluster=0 -d me/app 

或者你可以通过你的撰写文件来设置它们 :

 node: environment: - environment=dev - cluster=0 

您的Dockerfile CMD可以使用该环境variables,但是,如问题5509中所述 ,您需要以sh -c格式执行此操作:

 CMD ["sh", "-c", "node server.js ${cluster} ${environment}"] 

解释是shell负责扩展环境variables,而不是Docker。 当您使用JSON语法时 ,您明确要求您的命令绕过shell并直接执行。

与Builder RUN相同的想法(也适用于CMD ):

与shellforms不同,execforms不会调用命令shell。
这意味着正常的shell处理不会发生。

例如, RUN [ "echo", "$HOME" ]不会在$HOME上进行variablesreplace。 如果你想要shell处理,那么使用shellforms或者直接执行一个shell,例如: RUN [ "sh", "-c", "echo $HOME" ]

当使用exec表单并直接执行一个shell时,就像在shell表单的情况下一样,shell是在执行环境variables扩展,而不是docker。

另一个select是使用ENTRYPOINT指定该node是可运行的可执行文件, CMD提供参数。 这个文档在Exec form ENTRYPOINT示例中有一个例子 。

使用这种方法,你的Dockerfile看起来就像这样

 FROM ... ENTRYPOINT [ "node", "server.js" ] CMD [ "0", "dev" ] 

在dev中运行它将使用相同的命令

 docker run -p 9000:9000 -d me/app 

并运行它prod你会传递参数到运行命令

 docker run -p 9000:9000 -d me/app 1 prod 

您可能希望完全忽略CMD并始终将0 dev1 prod作为parameter passing给run命令。 这样你就不会不小心在产品的开发或开发容器中启动产品容器。

在Docker容器中这样做的典型方式是传入环境variables:

 docker run -p 9000:9000 -e NODE_ENV=dev -e CLUSTER=0 -d me/app