文章目录
- 环境
- 总结
- 测试
- 测试1
- 测试2
- 测试3
- 测试4
- 测试5
- 测试6
- 参考
环境
- RHEL 9.3
- Docker Community 24.0.7
总结
如果懒得看测试的详细信息,可以直接看结果:
- 一条
ENV
指令可以定义多个环境变量。 - Dockerfile里可以包含多条
ENV
指令。 - 环境变量的值不需要用双引号引起来,如果用了双引号,也会自动被去掉。
- 环境变量的值如果包含空格,可以用双引号引起来,或者用
\
将其转义。 - 环境变量的值如果包含双引号,可以用
\
将其转义。 - 在
ENV
指令里可以引用之前的ENV
指令里定义的环境变量。 - 在同一条
ENV
指令里,无法互相引用:- 如果是本条指令里新定义的变量,则当作没有定义。
- 如果是之前指令里定义过,本条指令里有修改的变量,则获取的仍然是之前指令里的值。
- 在启动容器时,可以通过
--env
选项覆盖Dockerfile里设置的环境变量。 - stage会继承其parent image的环境变量。
- 如果只是构建期的变量,不要用
ENV
指令,否则会影响image使用。 - 如果想要unset变量,需要把set和unset放到同一个
RUN
指令里。
测试
测试1
创建 Dockerfile
文件如下:
FROM alpine
ENV VAR1=value1 VAR2="value2" VAR3="hello world" \
VAR4=hello\ world
ENV VAR5="He said: \"It's good!\""
构建:
docker build -t kai0108_1 .
启动容器,查看环境变量:
➜ ~ docker run kai0108_1 env
VAR1=value1
VAR2=value2
VAR3=hello world
VAR4=hello world
VAR5=He said: "It's good!"
注:只列出了相关的环境变量。
总结:
- 一条
ENV
指令可以定义多个环境变量。 - Dockerfile里可以包含多条
ENV
指令。 - 环境变量的值不需要用双引号引起来,如果用了双引号,也会自动被去掉。
- 环境变量的值如果包含空格,可以用双引号引起来,或者用
\
将其转义。 - 环境变量的值如果包含双引号,可以用
\
将其转义。
测试2
创建 Dockerfile
文件如下:
FROM alpine
ENV VAR1=value1 VAR2=aaa${VAR1}bbb
ENV VAR3=ccc${VAR1}ddd
ENV VAR4=value4
ENV VAR5=aaa${VAR4}bbb VAR6=ccc${VAR5}ddd
ENV VAR7=value7
ENV VAR7=value8 VAR8=aaa${VAR7}bbb
启动容器,查看环境变量:
➜ ~ docker run kai0108_2 env
VAR1=value1
VAR2=aaabbb
VAR3=cccvalue1ddd
VAR4=value4
VAR5=aaavalue4bbb
VAR6=cccddd
VAR7=value8
VAR8=aaavalue7bbb
总结:
- 在
ENV
指令里可以引用之前的ENV
指令里定义的环境变量。 - 在同一条
ENV
指令里,无法互相引用:- 如果是本条指令里新定义的变量,则当作没有定义。
- 如果是之前指令里定义过,本条指令里有修改的变量,则获取的仍然是之前指令里的值。
测试3
创建 Dockerfile
文件如下:
FROM alpine
ENV VAR1=value1
启动容器,设置环境变量 VAR1
:
➜ ~ docker run --env VAR1=hello kai0108_3 env
VAR1=hello
总结:
- 在启动容器时,可以通过
--env
选项覆盖Dockerfile里设置的环境变量。
测试4
创建 Dockerfile
文件如下:
FROM alpine AS base
ENV VAR1=value1
FROM base
ENV VAR2=aaa${VAR1}bbb
启动容器,查看环境变量:
➜ ~ docker run kai0108_4 env
VAR1=value1
VAR2=aaavalue1bbb
总结:
- stage会继承其parent image的环境变量。
测试5
创建 Dockerfile
文件如下:
FROM ubuntu:trusty
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y curl
注: DEBIAN_FRONTEND=noninteractive
表示在 apt-get install
安装的过程中,使用缺省设置,不与用户交互(比如弹出对话框),当然如果不加 -y
选项,还是会让用户确认安装的。在构建时,无法与用户交互,所以要设置该环境变量(本例中安装 curl
其实并不会弹出对话框,只是个示例)。
构建:
docker build -t kai0108_5 .
注:构建会非常慢,因为要连接国外的网站。
启动容器,并进入容器:
docker run -it kai0108_5
安装 mail-stack-delivery
:
apt-get -y install mail-stack-delivery
注:这里安装 mail-stack-delivery
,只是为了测试安装过程中是否会弹出对话框。
在安装过程中,本来应该会弹出如下对话框:
但是实际上并没有弹出对话框。
原因很简单,因为有环境变量 DEBIAN_FRONTEND=noninteractive
。
本来,设置该环境变量只是为了在构建image时不与用户交互,但是在image里也保留了该环境变量,以至于影响了 apt-get install
的行为,这可能会对用户造成困扰。
解决办法有两种:
- 方法1:在
RUN
指令里设置环境变量,只对本指令有效:
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y curl
- 方法2:通过
ARG
指令设置变量,只在构建期有效:
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y curl
总结:
- 如果只是构建期的变量,不要用
ENV
指令,否则会影响image使用。
测试6
创建 Dockerfile
文件如下:
FROM alpine
ENV VAR1=value1
RUN echo aaa${VAR1}bbb > /tmp/a.txt
RUN unset VAR1
RUN echo ccc${VAR1}ddd > /tmp/b.txt
构建:
docker build -t kai0108_6 .
启动容器,并进入容器查看:
➜ ~ docker run -it kai0108_6
/ # cat /tmp/a.txt
aaavalue1bbb
/ # cat /tmp/b.txt
cccvalue1ddd
/ # env
VAR1=value1
......
可见,unset变量并不起作用。这是因为 ENV
指令会创建一个layer。
若想要unset变量,需要把set和unset放到同一个layer里,也就是同一个 RUN
指令里。
创建 Dockerfile
文件如下:
FROM alpine
RUN export VAR1=value1 \
&& echo aaa${VAR1}bbb > /tmp/a.txt \
&& unset VAR1 \
&& echo ccc${VAR1}ddd > /tmp/b.txt
RUN echo eee${VAR1}fff > /tmp/c.txt
构建:
docker build -t kai0108_7 .
启动容器,并进入容器查看:
➜ ~ docker run -it kai0108_7
/ # cat /tmp/a.txt
aaavalue1bbb
/ # cat /tmp/b.txt
cccddd
/ # cat /tmp/c.txt
eeefff
/ # env
HOSTNAME=13dcd240cd01
SHLVL=1
HOME=/root
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
可见,这次达到了预期的目的。
总结:
- 如果想要unset变量,需要把set和unset放到同一个
RUN
指令里。
参考
https://docs.docker.com/engine/reference/builder/#env
https://docs.docker.com/develop/develop-images/instructions/#env