2016-11-29 116 views
12

我是Docker的新手,我很難根據需要設置Docker容器。我有一個nodejs應用程序在啓動時可以帶兩個參數。例如,我可以使用使用docker run命令將參數傳遞給Dockerfile中的CMD

node server.js 0 dev

node server.js 1 prod

到和之間的生產模式和開發模式切換確定是否應該打開羣集。現在,我想創建一個參數做類似的事情泊塢窗的形象,我可以迄今唯一能做的就是調整Dockerfile有一個線

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

docker build -t me/app .建泊塢窗。

然後docker run -p 9000:9000 -d me/app運行碼頭。

,但如果我想切換到PROD模式,我需要改變Dockerfile CMD是

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

,我需要殺老一個偵聽端口9000和重建圖像。 我希望我能有這樣的事情

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

創建映像和運行用的NodeJS「環境」命令和「集羣」的論點,所以我並不需要改變Dockerfile和重建泊塢窗任何更多。我怎樣才能做到這一點?

回答

17

確保您Dockerfile聲明環境變量with ENV

ENV environment default_env_value 
ENV cluster default_cluster_value 

ENV <key> <value>形式可以是replaced inline

然後你可以pass an environment variable with docker run

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

或者你可以set them through your compose file

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

你Dockerfile CMD可以使用環境變量,但是,在issue 5509提到的,你需要在這樣做sh -c form:

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

解釋是shell負責擴展環境變量,而不是Docker。當您使用JSON語法時,您明確要求您的命令繞過shell並直接執行。

Builder RUN用同樣的想法(適用於CMD以及):

不同於殼的形式中,EXEC形式不調用命令殼。
這意味着正常的shell處理不會發生。

例如,RUN [ "echo", "$HOME" ]將不會在$HOME上進行變量替換。如果需要shell處理,則使用shell窗體或直接執行shell,例如:RUN [ "sh", "-c", "echo $HOME" ]

當使用exec表單並直接執行一個shell(如shell格式的情況)時,它是在執行環境變量擴展的shell,而不是docker。

+0

如何在Docker文件CMD中使用ENV,你能舉個例子嗎? – Jaaaaaaay

+0

@Jaaaaaaay'ENV'是您的'Dockerfile'中的聲明(請閱讀https://docs.docker.com/engine/reference/builder/#/env),然後將通過'docker run -e myvar = myvalue' – VonC

+0

@Jaaaaaaay我編輯了答案來解決你的問題。 – VonC

4

在Docker容器做到這一點的典型方法是在環境變量傳遞:

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

另一種選擇是使用ENTRYPOINT指定node是可執行文件運行,CMD提供的參數。該文檔在Exec form ENTRYPOINT example中有一個示例。

使用這種方法,您Dockerfile看起來像

FROM ... 

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

在開發中運行它會使用相同的命令

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

和PROD運行它,你會傳遞的參數運行命令

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

您可能希望完全忽略CMD,並始終將0 dev1 prod作爲參數傳遞給運行命令。這樣你就不會無意中在產品的開發或開發容器中啓動產品容器。

相關問題