Dockerfile - 将ENV设置为命令结果

时间:2016-01-20 22:10:59

标签: dockerfile env

是否可以将docker ENV变量设置为命令的结果? 像:

ENV MY_VAR whoami

我希望MY_VAR获得值“root”或者任何whoami返回

7 个答案:

答案 0 :(得分:14)

作为DarkSideF答案的补充。

您应该知道Dockerfile中的每一行/命令都在另一个容器中运行。

您可以这样做:

RUN export bleah=$(hostname -f);echo $bleah;

这是在一个容器中运行。

答案 1 :(得分:10)

我有同样的问题,并找到了通过在dockerfile中使用RUN命令将环境变量设置为函数的方法。

例如,我需要为Rails应用程序设置SECRET_KEY_BASE一次而不会像我运行时那样进行更改:

User.idCreator

相反,它写入Dockerfile字符串,如:

docker run  -e SECRET_KEY_BASE="$(openssl rand -hex 64)"
即使在bash登录后,

和我的env变量也可从root获得。 或者可能是

RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" >> /etc/bash.bashrc'

然后它在CMD和ENTRYPOINT命令中可用

Docker将其缓存为图层,只有在您更改之前的某些字符串时才会更改。

您也可以尝试different ways设置环境变量。

答案 2 :(得分:7)

此时,命令结果可以与RUN export一起使用,但不能分配给ENV变量。

已知问题:https://github.com/docker/docker/issues/29110

答案 3 :(得分:3)

这个答案是对 @DarkSideF

的回应

他提出的方法如下Dockerfile

RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" >> /etc/bash.bashrc'

/etc/bash.bashrc 中添加导出)

这很好,但环境变量只能用于进程/bin/bash,如果您尝试运行docker应用程序(例如Node.js应用程序),/etc/bash.bashrc将完全被忽略,您的应用程序在尝试访问SECRET_KEY_BASE时不知道process.env.SECRET_KEY_BASE是什么。

这就是为什么ENV关键字是每个人都尝试使用动态命令的原因,因为每次运行容器或使用exec命令时,Docker都会检查ENV并管道当前运行的流程中的每个值(类似于-e)。

一种解决方案是使用包装器(在此github issue中归功于 @duglin )。 在项目根目录中包含一个包装文件(例如envwrapper),其中包含:

#!/bin/bash
export SECRET_KEY_BASE="$(openssl rand -hex 64)"
export ANOTHER_ENV "hello world"
$*

然后在Dockerfile

...
COPY . .
RUN mv envwrapper /bin/.
RUN chmod 755 /bin/envwrapper
CMD envwrapper myapp

答案 4 :(得分:1)

不确定这是否是您想要的,但是为了将ENV var或ARGS注入.Dockerfile构建中,此模式有效。

在您的my_build.sh中:

echo getting version of osbase image to build from
OSBASE=$(grep "osbase_version" .version | sed 's/^.*: //')

echo building docker
docker build -f \
--build-arg ARTIFACT_TAG=$OSBASE \
PATH_TO_MY.Dockerfile \
-t my_artifact_home_url/bucketname:$TAG .

要在您的.Dockerfile中获得ARG,该片段可能如下所示:

FROM scratch
ARG ARTIFACT_TAG
FROM my_artifact_home_url/bucketname:${ARTIFACT_TAG}

或者为了在您的.Dockerfile中获取ENV,该代码段可能如下所示:

FROM someimage:latest
ARG ARTIFACT_TAG
ENV ARTIFACT_TAG=${ARTIFACT_TAG}

这个想法是您运行shell脚本,然后调用Dockerfile,并将args作为选项传递给构建。

答案 5 :(得分:1)

如果您使用 sh 运行命令,因为它似乎是 docker 中的默认设置。

你可以这样做:

Sub Lookup1()
    'Runs lookup for open positions & returns position that can apply
    'Provides data list of candidates with acceptable position codes
    'Declare the variables
        Dim JobClass1 As Integer
        Dim StaffID As Long
        Dim Last As String
        Dim Status As String
        Dim JobClass2 As Integer
     
    'error statement
        On Error GoTo errHandler:
    
    'clear the listbox
        lstJDOutput.RowSource = ""
        lstSelector.RowSource = ""
        **ListBox1.RowSourse = ""**
        lstCerts.RowSource = ""
        lstMatch.RowSource = ""
        Staff_Data.RowSource = ""
    
    'set the variable
       Status = Me.bx1.Value
       JobClass2 = Me.bx2.Value
       JobClass1 = Me.bx5.Value
       StaffID = Me.bx3.Value
       Last = Me.bx4.Value
               
    'if the results are nil clear the rowsource
    'Sheet6 is JDOutput
    'Sheet13 is Staffing_Output
        If Sheet6.Range("B10").Value = "" Then
            lstJDOutput.RowSource = ""
        If Sheet13.Range("B8").Value = "" Then
          lstSelector.RowSource = ""
        Else
    'add range to rowsource if range has values
        lstlstJDOutput.RowSource = "Filter_Staff5"
        lstSelector.RowSource = "Filter_Staff3"
        ListBox1.RowSource = "Filter_Staff3"
                             End If
                          End If
                      Exit Sub
      
      'if no JobClass or Status is selected for criteria search
      'Sheet12 is JD (job Description), Sheet4 is Staffing_Data
        With Sheet12
            If Me.bx2 = "" Then
                .Range("B6").Value = bx2
        With Sheet4
            If bx1 = "" Then
                .Range("F3").Value = ""
                .Range("S3").Value = bx3
                     End If
                            End With
                        End With
    
    'run the filters
        AdvFilterStaffing_Data
        AdvFilterJD
        AdvFilterStaffProgression
        AdvFilterMatch
    
    'if the results are nil then clear the rowsource to avoid an error
    'Sheet13 is Staffing_Output, Sheet6 is JDOutput
        With Sheet13
            If Sheet13.Range("C8").Value = "" Then
                 lstSelector.RowSource = ""
            If Sheet6.Range("B10").Value = "" Then
                 lstJDOutput.RowSource = ""
            Else
    'add range to rowsource if range has values
            lstJDOutput.RowSource = "Filter_Staff4"
            lstSelector.RowSource = "Filter_Staff3"
                        End If
                    End If
                End If
            End With
    'error block
        On Error GoTo 0
            Exit Sub**strong text**
errHandler::
        MsgBox "An Error has Occurred  " & vbCrLf & "The error number is:  " _
               & Err.Number & vbCrLf & Err.Description & vbCrLf & _
               "Please notify the administrator"
    End Sub

通过这种方式,您可以通过将输出重定向到您选择的 env 文件来构建 env 文件。它比必须定义配置文件等更明确。

然后,由于该文件可用于其他层,因此可以获取它并使用正在导出的变量。您创建 env 文件的方式并不重要。

然后,当您完成后,您可以删除该文件,使其对正在运行的容器不可用。

RUN echo "export VAR=`command`" >> /envfile RUN . /envfile; echo $VAR 是 env 文件的加载方式。

答案 6 :(得分:0)

作为@DarkSideF答案的补充,如果您想在构建过程中重用Dockerfile中的上一条命令的结果 ,则可以使用以下解决方法:< / p>

  1. 运行命令,将结果存储在文件中
  2. 使用命令替换将先前的结果从该文件转换为另一个命令

例如:

RUN echo "bla" > ./result
RUN echo $(cat ./result)

对于更干净的东西,您还可以使用以下gist,它提供了一个名为envstore.py的小型CLI:

RUN envstore.py set MY_VAR bla
RUN echo $(envstore.py get MY_VAR)

或者您可以使用具有类似CLI的python-dotenv库。