某些应用场景下,需要对Dokcer镜像加入环境变量,这时需要ENV
指令。本文本来具体对ENV
指令进行解析。
ENV 语法
ENV <key>=<value> ...
ENV 语义
· ENV
指令将环境变量的值设置为。
· ENV
指定的环境变量,可以在后续所有构建阶段使用,并且可用于行内替换使用。
· 环境变量的值可以被其他环境变量引用,此时,如果引号字符没有转义,将被删除。
· 与命令行解析类似,引号("
)和反斜杠(\
)用于包含空格的值,例如:
# 引号内的值可包含空格.
ENV MY_NAME="John Doe"
# 可以使用\来转义空格,还原其含义.
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy
· 允许在一个指令中同时设置多个环境变量,例如:
ENV MY_NAME="John Doe" MY_DOG=Rex\ The\ Dog \
MY_CAT=fluffy
· 使用构建后的镜像运行容器时,ENV
设置的环境变量保持不变,其已被保存到镜像中。
· 环境变量持久性可能会导致意料之外的副作用。例如,设置ENV DEBIAN_FRONTEND=noninteractive
会更改apt-get
的行为,并可能会混淆镜像的用户。
· 如果环境变量只在构建期间需要,而不希望保存到最终镜像中,则使用RUN
指令设置值或使用ARG
定义变量:
RUN
指令设置变量值:
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y ...
ARG
指令设置变量值:
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y ...
· 兼容语法
ENV
允许使用ENV <key> <value>
,省略=
。但是这种语法不允许在一个ENV
指令中同时设置多个环境变量。兼容语法主要用于兼容老版本,并不推荐使用。
ENV MY_VAR my-value
· 通过docker inspect
可以查看镜像包含的环境变量。
· 运行容器时,通过docker run --env<key>=<value>
可以覆盖镜像带有的环境变量。
ENV 示例
· 设置环境变量,容器启动时引用环境变量。
1) 进入/securitit/dockerfile/目录(根据个人选择,这是本文使用的目录),创建dockerfile
文件。
FROM nginx
MAINTAINER Securitit
ENV SECURITIT_NAME="Securitit"
ENV SECURITIT_EMAIL="Securitit@163.com"
ENV SECURITIT_DESC="${SECURITIT_NAME}'s is ${SECURITIT_EMAIL}"
CMD echo "${SECURITIT_DESC}"
配置文件中定义了SECURITIT_NAME
、SECURITIT_EMAIL
、SECURITIT_DESC
、,其中SECURITIT_DESC
引用了SECURITIT_NAME
和SECURITIT_EMAIL
,通过CMD
指定容器启动时输出SECURITIT_DESC
。
2) 执行如下的构建命令,基于dockerfile
构建镜像。
docker build -f /securitit/dockerfile/dockerfile -t securitit-nginx-env:1.0.0.1 .
3) 查看镜像信息。
docker images
4) 查看镜像元数据。
可以看到构建的镜像声明开放80和8080两个端口。
docker inspect -f {{".Config.Env"}} df091d578e94
5) 指定通过dockerfile
生成的镜像启动容器。
docker run --name securitit-nginx-env -it -p 80:80 securitit-nginx-env:1.0.0.1
· 通过兼容语法设置环境变量,容器启动时通过docker run --env<key>=<value>
覆盖镜像的环境变量。
1) 进入/securitit/dockerfile/目录(根据个人选择,这是本文使用的目录),创建dockerfile
文件。
FROM nginx
MAINTAINER Securitit
ENV SECURITIT_NAME="Securitit"
ENV SECURITIT_EMAIL="Securitit@163.com"
ENV SECURITIT_DESC="${SECURITIT_NAME}'s is ${SECURITIT_EMAIL}"
ENV SECURITIT_LABEL="BOOK BALL MUSIC"
CMD echo "${SECURITIT_DESC}, ${SECURITIT_NAME}'s label is ${SECURITIT_LABEL}"
配置文件中定义了SECURITIT_NAME
、SECURITIT_EMAIL
、SECURITIT_DESC
、SECURITIT_LABEL
,其中SECURITIT_DESC
引用了SECURITIT_NAME
、SECURITIT_EMAIL
和SECURITIT_LABEL
,通过CMD
指定容器启动时输出SECURITIT_DESC
。
2) 执行如下的构建命令,基于dockerfile
构建镜像。
docker build -f /securitit/dockerfile/dockerfile -t securitit-nginx-env:1.0.0.2 .
3) 查看镜像信息。
docker images
4) 查看镜像元数据。
docker inspect -f {{".Config.Env"}} 9a836d4afa55
5) 指定通过dockerfile
生成的镜像启动容器。
docker run --name securitit-nginx-env-v2 -it -p 80:80 --env SECURITIT_NAME="CSDN" securitit-nginx-env:1.0.0.2
容器启动命令中增加了--env SECURITIT_NAME="CSDN"
,目的是为了替换环境变量SECURITIT_NAME
的值,dockerfile中内容为${SECURITIT_DESC}, ${SECURITIT_NAME}'s label is ${SECURITIT_LABEL}
,docker run
时输出内容为Securitit's is Securitit@163.com, CSDN's label is BOOK BALL MUSIC
,发现开头的Securitit
未替换为CSDN
,原因是镜像构建时,SECURITIT_DESC
已做过替换,通过docker inspect
查看镜像元数据时,SECURITIT_DESC
值已变为Securitit's is Securitit@163.com
。
总结
环境变量对于系统和软件来说,还是十分关键的,环境变量可以描述其部分状态,并随便其整个生命周期。
若文中存在错误和不足,欢迎指正!