首页 > 解决方案 > Dockerfile: $HOME 已设置,但在使用它定义其他环境变量时变为空白

问题描述

我有一个简单的 Dockerfile,如下所示:

FROM alpine:3

RUN echo "$HOME"        # Prints '/root'
ENV OTHER_HOME="$HOME"
RUN echo "$OTHER_HOME"  # Prints nothing!

RUN echo "$PATH"        # Prints '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
ENV OTHER_PATH="$PATH"
RUN echo "$OTHER_PATH"  # Prints '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'

我这样构建:

docker build . --no-cache

输出令人困惑。$OTHER_PATH按预期打印,但$OTHER_HOME为空白。谁能解释这种行为?

% docker build . --no-cache
Sending build context to Docker daemon  335.4kB
Step 1/7 : FROM alpine:3 AS build-stage
 ---> e7d92cdc71fe
Step 2/7 : RUN echo "$HOME"
 ---> Running in f9cd2769cd78
/root
Removing intermediate container f9cd2769cd78
 ---> d13f007a1fdf
Step 3/7 : ENV OTHER_HOME="$HOME"
 ---> Running in 7493ca43f9f3
Removing intermediate container 7493ca43f9f3
 ---> 2d6acfe45228
Step 4/7 : RUN echo "$OTHER_HOME"
 ---> Running in fb960138f43e

Removing intermediate container fb960138f43e
 ---> caa9719aeee5
Step 5/7 : RUN echo "$PATH"
 ---> Running in fe1eacf50d30
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Removing intermediate container fe1eacf50d30
 ---> 17267879b82e
Step 6/7 : ENV OTHER_PATH="$PATH"
 ---> Running in 9dd894199ea4
Removing intermediate container 9dd894199ea4
 ---> fa43f399604f
Step 7/7 : RUN echo "$OTHER_PATH"
 ---> Running in 89d67d8b6cfe
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Removing intermediate container 89d67d8b6cfe
 ---> 440133fc0052
Successfully built 440133fc0052

更新:更奇怪的是,如果我手动分配$HOME,该值稍后可用!

FROM alpine:3

ENV HOME='/root'
RUN echo "$HOME"
ENV OTHER_HOME="$HOME"
RUN echo "$OTHER_HOME"

此 Dockerfile 导致:

% docker build . --no-cache
Sending build context to Docker daemon  335.4kB
Step 1/8 : FROM alpine:3 AS build-stage
 ---> e7d92cdc71fe
Step 2/8 : ENV HOME='/root'
 ---> Running in 4cb8a8e45b18
Removing intermediate container 4cb8a8e45b18
 ---> 40d0156fe68b
Step 3/8 : RUN echo "$HOME"
 ---> Running in 051cf7d138fb
/root
Removing intermediate container 051cf7d138fb
 ---> dc34c6859bcd
Step 4/8 : ENV OTHER_HOME="$HOME"
 ---> Running in 01dcc2788761
Removing intermediate container 01dcc2788761
 ---> 540ca4e9225a
Step 5/8 : RUN echo "$OTHER_HOME"
 ---> Running in 4e0d31d1f847
/root

标签: docker

解决方案


$HOME变量在容器由 RUN 步骤生成时设置。由于在之前的任何 ENV 或 ARG 步骤中未将其定义为 docker,因此您不能在新的 ENV 步骤中使用此变量。您可以通过检查基础映像来查看为 docker 定义的变量列表:

$ docker image inspect alpine:3 --format '{{json .Config.Env}}' | jq .
[
  "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
]

在这种情况下,唯一的变量是PATH。如果您运行构建,您将看到其他变量被定义,当您使用字符串语法时,一些由 shell 定义,而当使用 exec 语法时,其他变量由 docker/OS 定义:

$ cat df.env 
FROM alpine:3

RUN [ "env" ]
RUN env

$ DOCKER_BUILDKIT=0 docker build -t test-env -f df.env .
Sending build context to Docker daemon  25.09kB
Step 1/3 : FROM alpine:3
 ---> a187dde48cd2
Step 2/3 : RUN [ "env" ]
 ---> Running in 96b16e35b986
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=96b16e35b986
HOME=/root    
Removing intermediate container 96b16e35b986
 ---> b11077eeb243
Step 3/3 : RUN env 
 ---> Running in 90237b5b485f
HOSTNAME=90237b5b485f
SHLVL=1         
HOME=/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
Removing intermediate container 90237b5b485f
 ---> 2b3715def1df
Successfully built 2b3715def1df
Successfully tagged test-env:latest

在这种情况下,HOMEandHOSTNAME在您运行 exec 时被定义,并且SHLVLPWD您使用 shell ( /bin/sh) 时被添加到其中。


推荐阅读