簡體   English   中英

使用 docker run 命令將參數傳遞給 Dockerfile 中的 CMD

[英]Use docker run command to pass arguments to CMD in Dockerfile

我是 Docker 新手,我很難根據需要設置 docker 容器。 我有一個 nodejs 應用程序在啟動時可以帶兩個參數。 例如,我可以使用

node server.js 0 dev

或者

node server.js 1 prod

在生產模式和開發模式之間切換並確定是否應該打開集群。 現在我想創建帶有參數的 docker 圖像來做類似的事情,到目前為止我唯一能做的就是調整 Dockerfile 有一條線

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

docker build -t me/app . 構建碼頭工人。

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

但是如果我想切換到 prod 模式,我需要將 Dockerfile CMD 更改為

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

我需要殺死在端口 9000 上監聽的舊的並重建圖像。 我希望我能有類似的東西

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

創建映像並使用“環境”和“集群”參數運行 nodejs 命令,因此我不需要更改 Dockerfile 並重新構建 docker。 我怎樣才能做到這一點?

確保您的 Dockerfile使用ENV聲明環境變量:

ENV environment default_env_value
ENV cluster default_cluster_value

ENV <key> <value>形式可以被inline 替換

然后你可以使用 docker run 傳遞一個環境變量 請注意,每個變量都需要一個特定的-e標志才能運行。

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

或者您可以通過您的撰寫文件設置它們

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

您的 Dockerfile CMD可以使用該環境變量,但是,如issue 5509 中所述,您需要以sh -c形式執行此操作:

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

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

Builder RUN相同的想法(也適用於CMD ):

與 shell 形式不同,exec 形式不調用命令 shell。
這意味着不會發生正常的 shell 處理。

例如, RUN [ "echo", "$HOME" ]不會對$HOME進行變量替換。 如果你想要 shell 處理,那么要么使用 shell 形式,要么直接執行 shell,例如: RUN [ "sh", "-c", "echo $HOME" ]

當使用 exec 形式並直接執行 shell 時,就像 shell 形式一樣,是 shell 進行環境變量擴展,而不是 docker。

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

使用這種方法,您的 Dockerfile 將類似於

FROM ...

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

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

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

並在 prod 中運行它,您會將參數傳遞給 run 命令

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

您可能希望完全省略CMD並始終將0 dev1 prod作為參數傳遞給 run 命令。 這樣你就不會意外地在 dev 中啟動一個 prod 容器或在 prod 中啟動一個 dev 容器。

在 Docker 容器中執行此操作的典型方法是傳入環境變量:

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

選項 1) 使用 ENV 變量

文件

# we need to specify default values
ENV ENVIRONMENT=production
ENV CLUSTER=1

# there is no need to use parameters array
CMD node server.js ${CLUSTER} ${ENVIRONMENT}

運行 Docker

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

選項 2) 傳遞參數

文件

# use entrypoint instead of CMD and do not specify any arguments
ENTRYPOINT node server.js

運行 Docker

在 docker 鏡像名稱后傳遞參數

$ docker run -p 9000:9000 -d me/app 0 dev

有點偏離主題,存在構建參數以允許您在構建時傳入參數,這些參數顯示為環境變量,以在您的 docker 映像構建過程中使用:

$ docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 .

不確定這是否有幫助,但我以這種方式使用它並且它的作用就像一個魅力

CMD ["node", "--inspect=0.0.0.0:9229", "--max-old-space-size=256", "/home/api/index.js"]

我在docker-compose 上發現這個沒有用燒瓶設置環境變量

docker-compose.yml

version: '2'

services:
  app:
      image: python:2.7
      environment:
        - BAR=FOO
      volumes:
        - ./app.py:/app.py
      command: python app.py

應用程序

import os

print(os.environ["BAR"])

遲到了加入討論。 這是一個絕妙的技巧,您可以使用它來設置默認命令行參數,同時還支持用自定義參數覆蓋默認參數:

步驟#1 在您的 dockerfile 中調用您的程序,如下所示:

  ENV DEFAULT_ARGS "--some-default-flag=123 --foo --bar"
  CMD ["/bin/bash", "-c", "./my-nifty-executable   ${ARGS:-${DEFAULT_ARGS}}"]

步驟#2 現在何時可以像這樣調用 docker-image:

  # this will invoke it with DEFAULT_ARGS
  docker run mydockerimage   

  # but this will invoke the docker image with custom arguments
  docker run   --env  ARGS="--alternative-args  --and-then-some=123"   mydockerimage 

您還可以調整此技術以執行更復雜的參數評估,但您認為合適。 Bash 支持多種單行結構來幫助您實現這一目標。

希望這項技術可以幫助那里的一些人節省幾個小時的時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM