我们可以在DockerFile中将ARG传递给CMD吗?

时间:2019-01-22 11:30:55

标签: docker docker-compose dockerfile

如何在使用docker run命令的同时传递ENV变量,还可以告诉我是否在CMD中正确传递了ENV变量吗?

我要实现的主要事情是,我已将代码上传到gitlab上并创建了docker映像,以便可以创建Web应用程序容器。在该代码中,我们有一个文件Core.js,它带有2个参数1.组织名称和端口号。为此,我需要运行节点Core.js Org1 1401,节点Core.js Org2 1402等。有一个通过docker文件插入的shell脚本,我需要提供该文件的名称作为参数,以便它可以使用相同的Docker映像,但我可以为不同的组织创建多个容器

FROM alpine

LABEL MAINTAINER "CoE"
WORKDIR /

ARG proxy
ARG username
ARG pswd
ENV ORG_SCRIPT

RUN export http_proxy=$proxy                                                                    && \
    export https_proxy=$proxy                                                                   && \
    git clone -b master https://$username:$pswd@git.devops.company.net/dlr_ui         && \
    npm install                     

 EXPOSE 1401 1402 1403 1404 1405 1406 1407 1408
 WORKDIR /applications/package/ui_servers 
CMD ["sh","./${ORG_SCRIPT}"]    // It is not getting the script name over here. Can you tell if it is correct way or not. OR i should do:
CMD ["sh","./$ORG_SCRIPT"]

I'm getting error for both. Value is not coming to that variable.

Buid:
 docker build --no-cache --build-arg proxy=$http_proxy --build-arg username=dfadf--build-arg pswd=dsfadsf --build-arg -t uinodetest .


RUN:
docker run  -d -it -p 1401:1401 -e ORG_SCRIPT runOrg1.sh --name="Org1_UI" uinodetest

OR Other method i'm using is

FROM alpine

LABEL MAINTAINER "CoE"
WORKDIR /

ARG proxy
ARG username
ARG pswd
ENV ORG_NAME
ENV ORG_PORT

RUN export http_proxy=$proxy                                                                    && \
    export https_proxy=$proxy                                                                   && \
    git clone -b master https://$username:$pswd@git.devops.company.net/dlr_ui         && \
    npm install                     

 EXPOSE 1401 1402 1403 1404 1405 1406 1407 1408
 WORKDIR /applications/package/ui_servers 
CMD ["node","Core.js","$ORG_NAME","ORG_PORT"]



Buid:
 docker build --no-cache --build-arg proxy=$http_proxy --build-arg username=dfadf--build-arg pswd=dsfadsf --build-arg -t uinodetest .


RUN:
docker run  -d -it -p 1401:1401 -e ORG_NAME ORG1 -r ORG_PORT 1401 --name="Org1_UI" uinodetest

如果我缺少某些内容或语法错误,请告诉我。

3 个答案:

答案 0 :(得分:2)

Docker会将环境变量传递给您的容器,但是您需要一个外壳程序来将${var}语法解析为该变量。您已经接近:

CMD ["sh","./${ORG_SCRIPT}"]

我怀疑这不起作用的原因是因为传递给sh的arg尚未被扩展,并且sh没有处理该arg,它只是在运行它。相反,您需要:

CMD ["sh","-c","./${ORG_SCRIPT}"]

这与字符串/ shell语法几乎完全相同,我建议改为:

CMD ./${ORG_SCRIPT}

答案 1 :(得分:1)

这里有几个运动部件。

对于需要配置的内容,最简单的方法是在Node中使用process.env来引用它们,并且将它们作为命令行参数传递。在第二个示例中,例如,参考process.env.ORG_NAME

有些事情不需要配置。在第二个示例中,您可以为服务选择一个固定的TCP端口。即使您使用Express默认端口3000,也可以docker run -p 1401:3000docker run -p 1402:3000将不同的端口分配给运行同一映像的不同容器。在第一个示例中,您尝试使用环境变量来指定整个命令。不必打扰,只需使用标准的Docker命令行即可。

这将为您提供常规的Dockerfile之类的

FROM node:alpine
# Generally don't "git clone" in a Dockerfile.
WORKDIR /dlr_ui
COPY package.json package-lock.json ./
RUN npm install
COPY . ./
EXPOSE 3000
CMD ["node", "Core.js"]

您完全不必担心这个特定问题。你会像这样

docker run -d -p 1401:3000 -e ORG_NAME=ORG1 --name="Org1_UI" uinodetest

CMD,ENTRYPOINT和RUN命令有两种语法。看起来像JSON数组(但实际上不是)的形式直接运行给定的命令,而无需调用任何类型的shell或解释器或变量扩展。在第二个示例中,将使用文字字符串$ORG_NAMEORG_PORT作为参数来调用脚本。如果您只是编写看起来像命令的内容,而不使用JSONish语法,则会自动将其包装在sh -c中。

从语法上讲,我希望第一个示例可以完成您想要的操作(但请参见@BMitch的答案);但是直接直接传递命令会更简单

docker run -d -p 1401:1401 --name="Org1_UI" uinodetest ./runOrg1.sh

答案 2 :(得分:0)

我认为更好的方法是使用ENTRYPOINT然后添加CMD来执行help或类似的东西

ENTRYPOINT ["node","Core.js"]
CMD ["--help"]

然后,当您启动容器时,将$ORG_NAME$ORG_PORT传递给它。在这种情况下,泊坞窗将保留您的入口点,并将默认的CMD覆盖为--help,在这种情况下,将覆盖您已传递的其他选项,并确保将引号之间的命令保留为单个命令

因此,在这种情况下,您将按照以下方式运行容器:

docker run -it --name my_container myimage:latest "$ORG_NAME $ORG_PORT"
  

使用docker compose可以完成相同的情况。